diff --git a/README.md b/README.md index 2731bd0..2294c5e 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ From a design perspective the goal is to be the fastest, simplest, and cleanest - Bold priorities in task list. - Colors completed tasks in light gray and applies strikethrough. - Colors overdue tasks in purple and tasks due today in red. Both these colors are user customizable. -- User-customizable colors for projects, contexts, due dates, threshold dates, and arbitrary tags in task list. +- User-customizable colors for projects, contexts, due dates, threshold dates, creation dates, and arbitrary tags in task list. ## Mac-specific user interface features @@ -77,6 +77,7 @@ From a design perspective the goal is to be the fastest, simplest, and cleanest - U or Enter: update task - P: postpone task by X (user-entered) days - S: set due date +- Option+S: set threshold date - I: set priority to user-entered value (A-Z) - T: append text to end of selected tasks - R: prepend text to beginning of selected tasks (after priority and creation date if they exist) @@ -114,7 +115,7 @@ From a design perspective the goal is to be the fastest, simplest, and cleanest ## Filtering the task list -- Command+F: find (moves focus to the search field) +- Command+F: find within displayed tasks (moves focus to the search field) - F: define quick filters - 1: apply quick filter 1 - 2: apply quick filter 2 @@ -164,7 +165,7 @@ Your todo.txt file can get modified outside of TodoTxtMac, especially if you are ## Will this project be ported from Objective C to Swift? -At this time, there are no plans to move from Objective C to Swift. +When Apple officially deprecates Objective C, the plan is to migrate this project to Swift. # License diff --git a/TodoTxtMac.xcodeproj/project.pbxproj b/TodoTxtMac.xcodeproj/project.pbxproj index 045dd41..eb8ff67 100644 --- a/TodoTxtMac.xcodeproj/project.pbxproj +++ b/TodoTxtMac.xcodeproj/project.pbxproj @@ -8,10 +8,40 @@ /* Begin PBXBuildFile section */ 00165B2618DBD1EC00E137B8 /* TTMFiltersController.m in Sources */ = {isa = PBXBuildFile; fileRef = 00165B2518DBD1EC00E137B8 /* TTMFiltersController.m */; }; + 002218D81AA0D80800D6F3A0 /* TTMTask_Init_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218D71AA0D80800D6F3A0 /* TTMTask_Init_UnitTests.m */; }; + 002218DA1AA0EB3200D6F3A0 /* TTMTask_IsCompleted_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218D91AA0EB3200D6F3A0 /* TTMTask_IsCompleted_UnitTests.m */; }; + 002218DC1AA0F48D00D6F3A0 /* TTMTask_DueDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218DB1AA0F48D00D6F3A0 /* TTMTask_DueDate_UnitTests.m */; }; + 002218DE1AA107F600D6F3A0 /* TTMTask_CompletionDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218DD1AA107F600D6F3A0 /* TTMTask_CompletionDate_UnitTests.m */; }; + 002218E01AA1387900D6F3A0 /* TTMTask_ThresholdDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218DF1AA1387900D6F3A0 /* TTMTask_ThresholdDate_UnitTests.m */; }; + 002218E21AA139EB00D6F3A0 /* TTMTask_CreationDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218E11AA139EB00D6F3A0 /* TTMTask_CreationDate_UnitTests.m */; }; + 002218E41AA1704B00D6F3A0 /* TTMTask_DueState_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218E31AA1704B00D6F3A0 /* TTMTask_DueState_UnitTests.m */; }; + 002218E61AA173D100D6F3A0 /* TTMTask_ThresholdState_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218E51AA173D100D6F3A0 /* TTMTask_ThresholdState_UnitTests.m */; }; + 002218E81AA179CD00D6F3A0 /* TTMTask_MarkComplete_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218E71AA179CD00D6F3A0 /* TTMTask_MarkComplete_UnitTests.m */; }; + 002218EA1AA17B9B00D6F3A0 /* TTMTask_MarkIncomplete_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 002218E91AA17B9B00D6F3A0 /* TTMTask_MarkIncomplete_UnitTests.m */; }; 002EAE5918DBD24C008E7517 /* TTMAppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 002EAE5818DBD24C008E7517 /* TTMAppController.m */; }; 002EAE5E18DCAE5C008E7517 /* TTMFilterPredicates.m in Sources */ = {isa = PBXBuildFile; fileRef = 002EAE5D18DCAE5C008E7517 /* TTMFilterPredicates.m */; }; 003647E1193D562900FDF67A /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 003647E0193D562900FDF67A /* dsa_pub.pem */; }; - 0050D6841996AA38008F349B /* TTMTasklistMetadataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0050D6831996AA38008F349B /* TTMTasklistMetadataTests.m */; }; + 003F958F1AA2948D00A1FF47 /* TTMTask_ToggleCompletion_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F958E1AA2948D00A1FF47 /* TTMTask_ToggleCompletion_UnitTests.m */; }; + 003F95911AA2965600A1FF47 /* TTMDateUtility_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95901AA2965600A1FF47 /* TTMDateUtility_UnitTests.m */; }; + 003F95931AA296F300A1FF47 /* TTMTask_Priority_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95921AA296F300A1FF47 /* TTMTask_Priority_UnitTests.m */; }; + 003F95951AA2A35A00A1FF47 /* TTMTask_Projects_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95941AA2A35A00A1FF47 /* TTMTask_Projects_UnitTests.m */; }; + 003F95971AA2A44800A1FF47 /* TTMTask_Contexts_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95961AA2A44800A1FF47 /* TTMTask_Contexts_UnitTests.m */; }; + 003F95991AA2A64100A1FF47 /* TTMTask_SetDueDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95981AA2A64100A1FF47 /* TTMTask_SetDueDate_UnitTests.m */; }; + 003F959B1AA2B7A600A1FF47 /* TTMTask_RemoveDueDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F959A1AA2B7A600A1FF47 /* TTMTask_RemoveDueDate_UnitTests.m */; }; + 003F959E1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F959D1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.m */; }; + 003F95A01AA3F04C00A1FF47 /* TTMTask_Postpone_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F959F1AA3F04C00A1FF47 /* TTMTask_Postpone_UnitTests.m */; }; + 003F95A21AA3F41400A1FF47 /* TTMTask_IncreasePriority_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95A11AA3F41400A1FF47 /* TTMTask_IncreasePriority_UnitTests.m */; }; + 003F95A41AA3F5DC00A1FF47 /* TTMTask_DecreasePriority_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95A31AA3F5DC00A1FF47 /* TTMTask_DecreasePriority_UnitTests.m */; }; + 003F95A61AA3F68200A1FF47 /* TTMTask_RemovePriority_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95A51AA3F68200A1FF47 /* TTMTask_RemovePriority_UnitTests.m */; }; + 003F95A81AA3F83D00A1FF47 /* TTMTask_SetThresholdDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95A71AA3F83D00A1FF47 /* TTMTask_SetThresholdDate_UnitTests.m */; }; + 003F95AA1AA3F9C700A1FF47 /* TTMTask_IncrementThresholdDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95A91AA3F9C700A1FF47 /* TTMTask_IncrementThresholdDate_UnitTests.m */; }; + 003F95AC1AA3FBDA00A1FF47 /* TTMTask_DecrementThresholdDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95AB1AA3FBDA00A1FF47 /* TTMTask_DecrementThresholdDate_UnitTests.m */; }; + 003F95AE1AA3FC9600A1FF47 /* TTMTask_RemoveThresholdDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95AD1AA3FC9600A1FF47 /* TTMTask_RemoveThresholdDate_UnitTests.m */; }; + 003F95B01AA3FE4400A1FF47 /* TTMTask_AppendText_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95AF1AA3FE4400A1FF47 /* TTMTask_AppendText_UnitTests.m */; }; + 003F95B21AA4016200A1FF47 /* TTMTask_PrependText_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95B11AA4016200A1FF47 /* TTMTask_PrependText_UnitTests.m */; }; + 003F95B41AA40EC700A1FF47 /* TTMTask_IncrementDueDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95B31AA40EC700A1FF47 /* TTMTask_IncrementDueDate_UnitTests.m */; }; + 003F95B61AA40FB400A1FF47 /* TTMTask_DecrementDueDate_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 003F95B51AA40FB400A1FF47 /* TTMTask_DecrementDueDate_UnitTests.m */; }; + 0050D6841996AA38008F349B /* TTMTasklistMetadata_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0050D6831996AA38008F349B /* TTMTasklistMetadata_UnitTests.m */; }; 006062D818EC6B0800D147F2 /* NSUserDefaults+myColorSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 006062D718EC6B0800D147F2 /* NSUserDefaults+myColorSupport.m */; }; 006B26461A81C82D00B0E47A /* TTMFindReplace.xib in Resources */ = {isa = PBXBuildFile; fileRef = 006B26451A81C82D00B0E47A /* TTMFindReplace.xib */; }; 006BA79E19DB9CFD00C8F408 /* TTMTasklistMetadata.xib in Resources */ = {isa = PBXBuildFile; fileRef = 006BA79D19DB9CFD00C8F408 /* TTMTasklistMetadata.xib */; }; @@ -20,9 +50,7 @@ 0086C98518B54F1A00A427AA /* TTMTableViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0086C98418B54F1A00A427AA /* TTMTableViewDelegate.m */; }; 00930EAA18B536B00064D41B /* RegExCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 00930EA918B536B00064D41B /* RegExCategories.m */; }; 00930EAD18B5371B0064D41B /* TTMTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 00930EAC18B5371B0064D41B /* TTMTask.m */; }; - 00930EAE18B5371B0064D41B /* TTMTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 00930EAC18B5371B0064D41B /* TTMTask.m */; }; 00930EB118B537C10064D41B /* TTMDateUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 00930EB018B537C10064D41B /* TTMDateUtility.m */; }; - 00930EB218B537C10064D41B /* TTMDateUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 00930EB018B537C10064D41B /* TTMDateUtility.m */; }; 00A6058219E3733F00846B69 /* NSAlert+BlockMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = 00A6058119E3733F00846B69 /* NSAlert+BlockMethods.m */; }; 00B4CB9C18B43E8400313DAA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B4CB9B18B43E8400313DAA /* Cocoa.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 00B4CBA618B43E8400313DAA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 00B4CBA418B43E8400313DAA /* InfoPlist.strings */; }; @@ -35,10 +63,9 @@ 00B4CBBE18B43E8500313DAA /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B4CBBD18B43E8500313DAA /* XCTest.framework */; }; 00B4CBBF18B43E8500313DAA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00B4CB9B18B43E8400313DAA /* Cocoa.framework */; }; 00B4CBC718B43E8500313DAA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 00B4CBC518B43E8500313DAA /* InfoPlist.strings */; }; - 00B4CBC918B43E8500313DAA /* TodoTxtMacTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00B4CBC818B43E8500313DAA /* TodoTxtMacTests.m */; }; + 00B4CBC918B43E8500313DAA /* TTMTask_ReplaceText_UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00B4CBC818B43E8500313DAA /* TTMTask_ReplaceText_UnitTests.m */; }; 00B8C82518E48FFF008D9E48 /* TTMFieldEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = 00B8C82418E48FFF008D9E48 /* TTMFieldEditor.m */; }; 00D102B61991ABBE00D30237 /* TTMTasklistMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 00D102B51991ABBE00D30237 /* TTMTasklistMetadata.m */; }; - 00D102B71991ABBE00D30237 /* TTMTasklistMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 00D102B51991ABBE00D30237 /* TTMTasklistMetadata.m */; }; 00DE02EC19E37E340093338A /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00DE02EB19E37E340093338A /* Sparkle.framework */; }; 00DE02ED19E37E650093338A /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00DE02EB19E37E340093338A /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 00EAAB9718E0C168009CBE8C /* TTMPredicateEditorDateRowTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 00EAAB9618E0C168009CBE8C /* TTMPredicateEditorDateRowTemplate.m */; }; @@ -79,12 +106,43 @@ /* Begin PBXFileReference section */ 00165B2418DBD1EC00E137B8 /* TTMFiltersController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTMFiltersController.h; sourceTree = ""; }; 00165B2518DBD1EC00E137B8 /* TTMFiltersController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMFiltersController.m; sourceTree = ""; }; + 002218D71AA0D80800D6F3A0 /* TTMTask_Init_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_Init_UnitTests.m; sourceTree = ""; }; + 002218D91AA0EB3200D6F3A0 /* TTMTask_IsCompleted_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_IsCompleted_UnitTests.m; sourceTree = ""; }; + 002218DB1AA0F48D00D6F3A0 /* TTMTask_DueDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_DueDate_UnitTests.m; sourceTree = ""; }; + 002218DD1AA107F600D6F3A0 /* TTMTask_CompletionDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_CompletionDate_UnitTests.m; sourceTree = ""; }; + 002218DF1AA1387900D6F3A0 /* TTMTask_ThresholdDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_ThresholdDate_UnitTests.m; sourceTree = ""; }; + 002218E11AA139EB00D6F3A0 /* TTMTask_CreationDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_CreationDate_UnitTests.m; sourceTree = ""; }; + 002218E31AA1704B00D6F3A0 /* TTMTask_DueState_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_DueState_UnitTests.m; sourceTree = ""; }; + 002218E51AA173D100D6F3A0 /* TTMTask_ThresholdState_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_ThresholdState_UnitTests.m; sourceTree = ""; }; + 002218E71AA179CD00D6F3A0 /* TTMTask_MarkComplete_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_MarkComplete_UnitTests.m; sourceTree = ""; }; + 002218E91AA17B9B00D6F3A0 /* TTMTask_MarkIncomplete_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_MarkIncomplete_UnitTests.m; sourceTree = ""; }; 002EAE5718DBD24C008E7517 /* TTMAppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTMAppController.h; sourceTree = ""; }; 002EAE5818DBD24C008E7517 /* TTMAppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMAppController.m; sourceTree = ""; }; 002EAE5C18DCAE5C008E7517 /* TTMFilterPredicates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTMFilterPredicates.h; sourceTree = ""; }; 002EAE5D18DCAE5C008E7517 /* TTMFilterPredicates.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMFilterPredicates.m; sourceTree = ""; }; 003647E0193D562900FDF67A /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = ""; }; - 0050D6831996AA38008F349B /* TTMTasklistMetadataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTasklistMetadataTests.m; sourceTree = ""; }; + 003F958E1AA2948D00A1FF47 /* TTMTask_ToggleCompletion_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_ToggleCompletion_UnitTests.m; sourceTree = ""; }; + 003F95901AA2965600A1FF47 /* TTMDateUtility_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMDateUtility_UnitTests.m; sourceTree = ""; }; + 003F95921AA296F300A1FF47 /* TTMTask_Priority_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_Priority_UnitTests.m; sourceTree = ""; }; + 003F95941AA2A35A00A1FF47 /* TTMTask_Projects_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_Projects_UnitTests.m; sourceTree = ""; }; + 003F95961AA2A44800A1FF47 /* TTMTask_Contexts_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_Contexts_UnitTests.m; sourceTree = ""; }; + 003F95981AA2A64100A1FF47 /* TTMTask_SetDueDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_SetDueDate_UnitTests.m; sourceTree = ""; }; + 003F959A1AA2B7A600A1FF47 /* TTMTask_RemoveDueDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_RemoveDueDate_UnitTests.m; sourceTree = ""; }; + 003F959C1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableAttributableString+ColorRegExMatches.h"; sourceTree = ""; }; + 003F959D1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableAttributableString+ColorRegExMatches.m"; sourceTree = ""; }; + 003F959F1AA3F04C00A1FF47 /* TTMTask_Postpone_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_Postpone_UnitTests.m; sourceTree = ""; }; + 003F95A11AA3F41400A1FF47 /* TTMTask_IncreasePriority_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_IncreasePriority_UnitTests.m; sourceTree = ""; }; + 003F95A31AA3F5DC00A1FF47 /* TTMTask_DecreasePriority_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_DecreasePriority_UnitTests.m; sourceTree = ""; }; + 003F95A51AA3F68200A1FF47 /* TTMTask_RemovePriority_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_RemovePriority_UnitTests.m; sourceTree = ""; }; + 003F95A71AA3F83D00A1FF47 /* TTMTask_SetThresholdDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_SetThresholdDate_UnitTests.m; sourceTree = ""; }; + 003F95A91AA3F9C700A1FF47 /* TTMTask_IncrementThresholdDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_IncrementThresholdDate_UnitTests.m; sourceTree = ""; }; + 003F95AB1AA3FBDA00A1FF47 /* TTMTask_DecrementThresholdDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_DecrementThresholdDate_UnitTests.m; sourceTree = ""; }; + 003F95AD1AA3FC9600A1FF47 /* TTMTask_RemoveThresholdDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_RemoveThresholdDate_UnitTests.m; sourceTree = ""; }; + 003F95AF1AA3FE4400A1FF47 /* TTMTask_AppendText_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_AppendText_UnitTests.m; sourceTree = ""; }; + 003F95B11AA4016200A1FF47 /* TTMTask_PrependText_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_PrependText_UnitTests.m; sourceTree = ""; }; + 003F95B31AA40EC700A1FF47 /* TTMTask_IncrementDueDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_IncrementDueDate_UnitTests.m; sourceTree = ""; }; + 003F95B51AA40FB400A1FF47 /* TTMTask_DecrementDueDate_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTask_DecrementDueDate_UnitTests.m; sourceTree = ""; }; + 0050D6831996AA38008F349B /* TTMTasklistMetadata_UnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMTasklistMetadata_UnitTests.m; sourceTree = ""; }; 006062D618EC6B0800D147F2 /* NSUserDefaults+myColorSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+myColorSupport.h"; sourceTree = ""; }; 006062D718EC6B0800D147F2 /* NSUserDefaults+myColorSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSUserDefaults+myColorSupport.m"; sourceTree = ""; }; 006B26451A81C82D00B0E47A /* TTMFindReplace.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TTMFindReplace.xib; sourceTree = ""; }; @@ -122,7 +180,7 @@ 00B4CBBD18B43E8500313DAA /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 00B4CBC418B43E8500313DAA /* TodoTxtMacTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TodoTxtMacTests-Info.plist"; sourceTree = ""; }; 00B4CBC618B43E8500313DAA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 00B4CBC818B43E8500313DAA /* TodoTxtMacTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TodoTxtMacTests.m; sourceTree = ""; }; + 00B4CBC818B43E8500313DAA /* TTMTask_ReplaceText_UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TTMTask_ReplaceText_UnitTests.m; sourceTree = ""; }; 00B8C82318E48FFF008D9E48 /* TTMFieldEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTMFieldEditor.h; sourceTree = ""; }; 00B8C82418E48FFF008D9E48 /* TTMFieldEditor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTMFieldEditor.m; sourceTree = ""; }; 00D102B41991ABBE00D30237 /* TTMTasklistMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTMTasklistMetadata.h; sourceTree = ""; }; @@ -221,6 +279,8 @@ 006062D718EC6B0800D147F2 /* NSUserDefaults+myColorSupport.m */, 00A6058019E3733F00846B69 /* NSAlert+BlockMethods.h */, 00A6058119E3733F00846B69 /* NSAlert+BlockMethods.m */, + 003F959C1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.h */, + 003F959D1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.m */, ); name = Libraries; sourceTree = ""; @@ -299,9 +359,38 @@ 00B4CBC218B43E8500313DAA /* TodoTxtMacTests */ = { isa = PBXGroup; children = ( - 00B4CBC818B43E8500313DAA /* TodoTxtMacTests.m */, 00B4CBC318B43E8500313DAA /* Supporting Files */, - 0050D6831996AA38008F349B /* TTMTasklistMetadataTests.m */, + 003F95901AA2965600A1FF47 /* TTMDateUtility_UnitTests.m */, + 0050D6831996AA38008F349B /* TTMTasklistMetadata_UnitTests.m */, + 002218D71AA0D80800D6F3A0 /* TTMTask_Init_UnitTests.m */, + 003F95921AA296F300A1FF47 /* TTMTask_Priority_UnitTests.m */, + 002218DD1AA107F600D6F3A0 /* TTMTask_CompletionDate_UnitTests.m */, + 002218E11AA139EB00D6F3A0 /* TTMTask_CreationDate_UnitTests.m */, + 002218DB1AA0F48D00D6F3A0 /* TTMTask_DueDate_UnitTests.m */, + 002218E31AA1704B00D6F3A0 /* TTMTask_DueState_UnitTests.m */, + 002218DF1AA1387900D6F3A0 /* TTMTask_ThresholdDate_UnitTests.m */, + 002218E51AA173D100D6F3A0 /* TTMTask_ThresholdState_UnitTests.m */, + 002218D91AA0EB3200D6F3A0 /* TTMTask_IsCompleted_UnitTests.m */, + 002218E71AA179CD00D6F3A0 /* TTMTask_MarkComplete_UnitTests.m */, + 002218E91AA17B9B00D6F3A0 /* TTMTask_MarkIncomplete_UnitTests.m */, + 003F958E1AA2948D00A1FF47 /* TTMTask_ToggleCompletion_UnitTests.m */, + 003F95941AA2A35A00A1FF47 /* TTMTask_Projects_UnitTests.m */, + 003F95961AA2A44800A1FF47 /* TTMTask_Contexts_UnitTests.m */, + 003F95981AA2A64100A1FF47 /* TTMTask_SetDueDate_UnitTests.m */, + 003F959F1AA3F04C00A1FF47 /* TTMTask_Postpone_UnitTests.m */, + 003F95B31AA40EC700A1FF47 /* TTMTask_IncrementDueDate_UnitTests.m */, + 003F95B51AA40FB400A1FF47 /* TTMTask_DecrementDueDate_UnitTests.m */, + 003F959A1AA2B7A600A1FF47 /* TTMTask_RemoveDueDate_UnitTests.m */, + 003F95A11AA3F41400A1FF47 /* TTMTask_IncreasePriority_UnitTests.m */, + 003F95A31AA3F5DC00A1FF47 /* TTMTask_DecreasePriority_UnitTests.m */, + 003F95A51AA3F68200A1FF47 /* TTMTask_RemovePriority_UnitTests.m */, + 003F95A71AA3F83D00A1FF47 /* TTMTask_SetThresholdDate_UnitTests.m */, + 003F95A91AA3F9C700A1FF47 /* TTMTask_IncrementThresholdDate_UnitTests.m */, + 003F95AB1AA3FBDA00A1FF47 /* TTMTask_DecrementThresholdDate_UnitTests.m */, + 003F95AD1AA3FC9600A1FF47 /* TTMTask_RemoveThresholdDate_UnitTests.m */, + 003F95AF1AA3FE4400A1FF47 /* TTMTask_AppendText_UnitTests.m */, + 003F95B11AA4016200A1FF47 /* TTMTask_PrependText_UnitTests.m */, + 00B4CBC818B43E8500313DAA /* TTMTask_ReplaceText_UnitTests.m */, ); path = TodoTxtMacTests; sourceTree = ""; @@ -494,6 +583,7 @@ 00B4CBAF18B43E8400313DAA /* TTMDocument.m in Sources */, 00930EAA18B536B00064D41B /* RegExCategories.m in Sources */, 00B4CBA818B43E8400313DAA /* main.m in Sources */, + 003F959E1AA2C42700A1FF47 /* NSMutableAttributableString+ColorRegExMatches.m in Sources */, 00EAAB9718E0C168009CBE8C /* TTMPredicateEditorDateRowTemplate.m in Sources */, 00EC5EA118E3BC920021242B /* TTMAppDelegate.m in Sources */, 00F811EF18D53F7300379B99 /* TTMPreferencesController.m in Sources */, @@ -508,11 +598,37 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00930EAE18B5371B0064D41B /* TTMTask.m in Sources */, - 00D102B71991ABBE00D30237 /* TTMTasklistMetadata.m in Sources */, - 00930EB218B537C10064D41B /* TTMDateUtility.m in Sources */, - 00B4CBC918B43E8500313DAA /* TodoTxtMacTests.m in Sources */, - 0050D6841996AA38008F349B /* TTMTasklistMetadataTests.m in Sources */, + 003F95911AA2965600A1FF47 /* TTMDateUtility_UnitTests.m in Sources */, + 002218DA1AA0EB3200D6F3A0 /* TTMTask_IsCompleted_UnitTests.m in Sources */, + 003F95971AA2A44800A1FF47 /* TTMTask_Contexts_UnitTests.m in Sources */, + 003F958F1AA2948D00A1FF47 /* TTMTask_ToggleCompletion_UnitTests.m in Sources */, + 003F95A41AA3F5DC00A1FF47 /* TTMTask_DecreasePriority_UnitTests.m in Sources */, + 002218EA1AA17B9B00D6F3A0 /* TTMTask_MarkIncomplete_UnitTests.m in Sources */, + 002218E41AA1704B00D6F3A0 /* TTMTask_DueState_UnitTests.m in Sources */, + 003F95A81AA3F83D00A1FF47 /* TTMTask_SetThresholdDate_UnitTests.m in Sources */, + 003F95B61AA40FB400A1FF47 /* TTMTask_DecrementDueDate_UnitTests.m in Sources */, + 002218DC1AA0F48D00D6F3A0 /* TTMTask_DueDate_UnitTests.m in Sources */, + 002218E61AA173D100D6F3A0 /* TTMTask_ThresholdState_UnitTests.m in Sources */, + 002218E21AA139EB00D6F3A0 /* TTMTask_CreationDate_UnitTests.m in Sources */, + 002218E81AA179CD00D6F3A0 /* TTMTask_MarkComplete_UnitTests.m in Sources */, + 00B4CBC918B43E8500313DAA /* TTMTask_ReplaceText_UnitTests.m in Sources */, + 003F95A61AA3F68200A1FF47 /* TTMTask_RemovePriority_UnitTests.m in Sources */, + 003F95AE1AA3FC9600A1FF47 /* TTMTask_RemoveThresholdDate_UnitTests.m in Sources */, + 003F95A21AA3F41400A1FF47 /* TTMTask_IncreasePriority_UnitTests.m in Sources */, + 003F95951AA2A35A00A1FF47 /* TTMTask_Projects_UnitTests.m in Sources */, + 003F95B41AA40EC700A1FF47 /* TTMTask_IncrementDueDate_UnitTests.m in Sources */, + 003F95AC1AA3FBDA00A1FF47 /* TTMTask_DecrementThresholdDate_UnitTests.m in Sources */, + 0050D6841996AA38008F349B /* TTMTasklistMetadata_UnitTests.m in Sources */, + 003F95B21AA4016200A1FF47 /* TTMTask_PrependText_UnitTests.m in Sources */, + 003F959B1AA2B7A600A1FF47 /* TTMTask_RemoveDueDate_UnitTests.m in Sources */, + 002218D81AA0D80800D6F3A0 /* TTMTask_Init_UnitTests.m in Sources */, + 003F95AA1AA3F9C700A1FF47 /* TTMTask_IncrementThresholdDate_UnitTests.m in Sources */, + 002218E01AA1387900D6F3A0 /* TTMTask_ThresholdDate_UnitTests.m in Sources */, + 003F95B01AA3FE4400A1FF47 /* TTMTask_AppendText_UnitTests.m in Sources */, + 002218DE1AA107F600D6F3A0 /* TTMTask_CompletionDate_UnitTests.m in Sources */, + 003F95A01AA3F04C00A1FF47 /* TTMTask_Postpone_UnitTests.m in Sources */, + 003F95991AA2A64100A1FF47 /* TTMTask_SetDueDate_UnitTests.m in Sources */, + 003F95931AA296F300A1FF47 /* TTMTask_Priority_UnitTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -644,6 +760,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUNDLE_LOADER = ""; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -654,6 +771,7 @@ INFOPLIST_FILE = "TodoTxtMac/TodoTxtMac-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + TEST_HOST = ""; WRAPPER_EXTENSION = app; }; name = Debug; @@ -672,6 +790,7 @@ INFOPLIST_FILE = "TodoTxtMac/TodoTxtMac-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/TodoTxtMac/Base.lproj/TTMDocument.xib b/TodoTxtMac/Base.lproj/TTMDocument.xib index 8dce91f..34e9a34 100644 --- a/TodoTxtMac/Base.lproj/TTMDocument.xib +++ b/TodoTxtMac/Base.lproj/TTMDocument.xib @@ -132,7 +132,7 @@ - + predicate rawText contains[cd] $value diff --git a/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.h b/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.h new file mode 100644 index 0000000..5f049a8 --- /dev/null +++ b/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.h @@ -0,0 +1,67 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import + +@interface NSMutableAttributedString (ColorRegExMatches) + +/*! + * @method applyColor:toRegexPatternMatches: + * @abstract Adds foreground color attributes to a mutable attributed string based for all regular + * epxression matches. + * @param color Color to apply + * @param regExPattern Regular expression pattern to apply colors to matches + */ +- (void)applyColor:(NSColor*)color toRegexPatternMatches:(NSString*)regExPattern; + +/*! + * @method applyColorToFullStringRange: + * @abstract Adds foreground color attributes to the entire mutable attributed string. + * @param color Color to apply + */ +- (void)applyColorToFullStringRange:(NSColor*)color; + +@end diff --git a/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.m b/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.m new file mode 100644 index 0000000..ac12314 --- /dev/null +++ b/TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.m @@ -0,0 +1,67 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "NSMutableAttributableString+ColorRegExMatches.h" +#import "RegExCategories.h" + +@implementation NSMutableAttributedString (ColorRegExMatches) + +- (void)applyColor:(NSColor*)color toRegexPatternMatches:(NSString*)regExPattern { + NSArray *matches = [self.string matchesWithDetails:RX(regExPattern)]; + for (RxMatch *match in matches) { + [self addAttribute:NSForegroundColorAttributeName + value:color + range:match.range]; + } +} + +- (void)applyColorToFullStringRange:(NSColor*)color { + [self addAttribute:NSForegroundColorAttributeName + value:color + range:NSMakeRange(0, [self.string length])]; +} + +@end diff --git a/TodoTxtMac/TTMAppController.m b/TodoTxtMac/TTMAppController.m index 4b8f600..2ae7fc0 100644 --- a/TodoTxtMac/TTMAppController.m +++ b/TodoTxtMac/TTMAppController.m @@ -87,6 +87,7 @@ @NO, @"useCustomColorForTags", @NO, @"useCustomColorForDueDates", @NO, @"useCustomColorForThresholdDates", + @NO, @"useCustomColorForCreationDates", [NSArchiver archivedDataWithRootObject:[NSColor redColor]], @"dueTodayColor", [NSArchiver archivedDataWithRootObject:[NSColor purpleColor]], @"overdueColor", [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"projectColor", @@ -94,6 +95,7 @@ [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"tagColor", [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"dueDateColor", [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"thresholdDateColor", + [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"creationDateColor", @NO, @"escapeKeyCancelsAllTextChanges", @NO, @"openDefaultTodoFileOnStartup", @"", @"defaultTodoFilePath", diff --git a/TodoTxtMac/TTMDateUtility.m b/TodoTxtMac/TTMDateUtility.m index 3eac3e0..fb2491b 100644 --- a/TodoTxtMac/TTMDateUtility.m +++ b/TodoTxtMac/TTMDateUtility.m @@ -60,7 +60,6 @@ + (NSDate*)convertStringToDate:(NSString*)dateString { // Convert dateString to NSDate. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; - [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; return [dateFormatter dateFromString:dateTimeString]; } @@ -70,8 +69,7 @@ + (NSString*)convertDateToString:(NSDate*)date { } NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; - [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; - return [dateFormatter stringFromDate:date]; + return [dateFormatter stringFromDate:date]; } + (NSDate*)today { @@ -94,13 +92,8 @@ + (NSDate*)dateWithoutTime:(NSDate*)date { return nil; } NSDateComponents *comps = [[NSCalendar currentCalendar] - components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit| - NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit + components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:date]; - [comps setHour:00]; - [comps setMinute:00]; - [comps setSecond:00]; - [comps setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; return [[NSCalendar currentCalendar] dateFromComponents:comps]; } @@ -182,7 +175,6 @@ + (NSDate*)relativeDateFromWeekdayName:(NSString*)weekdayName } NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; [dateFormatter setLocale:[NSLocale currentLocale]]; [dateFormatter setDateFormat:dateFormat]; diff --git a/TodoTxtMac/TTMDocument.h b/TodoTxtMac/TTMDocument.h index 5e1c062..ca63593 100644 --- a/TodoTxtMac/TTMDocument.h +++ b/TodoTxtMac/TTMDocument.h @@ -82,6 +82,7 @@ typedef void (^TaskChangeBlock)(id, NSUInteger, BOOL*); // Window controls @property (nonatomic, retain) IBOutlet NSTextField *textField; @property (nonatomic, retain) IBOutlet NSSearchField *searchField; +@property (nonatomic, retain) IBOutlet NSPredicate *searchFieldPredicate; @property (nonatomic, retain) IBOutlet TTMTableView *tableView; @property (nonatomic, retain) IBOutlet TTMTableViewDelegate *tableViewDelegate; @property (nonatomic, retain) IBOutlet NSArrayController *arrayController; @@ -377,6 +378,14 @@ typedef void (^TaskChangeBlock)(id, NSUInteger, BOOL*); #pragma mark - Filter Methods +/*! + * @method combineFilterPresetPredicate:withSearchFilterPredicate + * @abstract Combines the filter preset predicate applied to the task list with the search field + * predicate in an "AND" fashion. + */ +- (NSPredicate*)combineFilterPresetPredicate:(NSPredicate*)filterPresetPredicate + withSearchFilterPredicate:(NSPredicate*)searchFilterPredicate; + /*! * @method filterTaskListUsingTagforPreset: * @abstract Sets the filter on the task list to a numbered preset, based on the sender's tag. diff --git a/TodoTxtMac/TTMDocument.m b/TodoTxtMac/TTMDocument.m index e8b3df4..36f4f97 100644 --- a/TodoTxtMac/TTMDocument.m +++ b/TodoTxtMac/TTMDocument.m @@ -76,10 +76,10 @@ @implementation TTMDocument [(TTMTask*)task removePriority]; }; TaskChangeBlock _increaseDueDateByOneDay = ^(id task, NSUInteger idx, BOOL *stop) { - [(TTMTask*)task postponeTask:1]; + [(TTMTask*)task incrementDueDate:1]; }; TaskChangeBlock _decreaseDueDateByOneDay = ^(id task, NSUInteger idx, BOOL *stop) { - [(TTMTask*)task postponeTask:-1]; + [(TTMTask*)task decrementDueDate:1]; }; TaskChangeBlock _removeDueDate = ^(id task, NSUInteger idx, BOOL *stop) { [(TTMTask*)task removeDueDate]; @@ -88,10 +88,10 @@ @implementation TTMDocument [(TTMTask*)task removeThresholdDate]; }; TaskChangeBlock _increaseThresholdDateByOneDay = ^(id task, NSUInteger idx, BOOL *stop) { - [(TTMTask*)task incrementThresholdDay:1]; + [(TTMTask*)task incrementThresholdDate:1]; }; TaskChangeBlock _decreaseThresholdDateByOneDay = ^(id task, NSUInteger idx, BOOL *stop) { - [(TTMTask*)task decrementThresholdDay:1]; + [(TTMTask*)task decrementThresholdDate:1]; }; #pragma mark - init Methods @@ -132,6 +132,9 @@ - (void)awakeFromNib { // Observe array controller selection to update "selected tasks" count in status bar [self.arrayController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:nil]; + + // Observe self to update search field filter + [self addObserver:self forKeyPath:@"searchFieldPredicate" options:NSKeyValueObservingOptionNew context:nil]; } - (NSString *)windowNibName { @@ -385,6 +388,7 @@ - (void)addNewTasksFromPasteBoard:(NSPasteboard*)pasteboard { componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]]; [self addTasksFromArray:rawTextStrings removeAllTasksFirst:NO]; + [self reapplyActiveFilterPredicate]; [self refreshTaskListWithSave:YES]; } @@ -807,6 +811,26 @@ - (IBAction)sortTaskListUsingTagforPreset:(id)sender { #pragma mark - Filter Methods +- (NSPredicate*)combineFilterPresetPredicate:(NSPredicate*)filterPresetPredicate + withSearchFilterPredicate:(NSPredicate*)searchFilterPredicate { + if (searchFilterPredicate == nil && filterPresetPredicate == nil) { + return nil; + } + + if (searchFilterPredicate == nil && filterPresetPredicate != nil) { + return filterPresetPredicate; + } + + if (searchFilterPredicate != nil && filterPresetPredicate == nil) { + return searchFilterPredicate; + } + + // if (searchFilterPredicate != nil && filterPresetPredicate != nil) + NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: + @[filterPresetPredicate, searchFilterPredicate]]; + return predicate; +} + - (IBAction)filterTaskListUsingTagforPreset:(id)sender { [self changeActiveFilterPredicateToPreset:[sender tag]]; } @@ -816,12 +840,14 @@ - (void)removeTaskListFilter { } - (void)reapplyActiveFilterPredicate { - self.activeFilterPredicate = [TTMFilterPredicates activeFilterPredicate]; + [self changeActiveFilterPredicateToPreset:self.activeFilterPredicateNumber]; } - (void)changeActiveFilterPredicateToPreset:(NSUInteger)presetNumber { - self.activeFilterPredicate = [TTMFilterPredicates - getFilterPredicateFromPresetNumber:presetNumber]; + NSPredicate *filterPresetPredicate = [TTMFilterPredicates + getFilterPredicateFromPresetNumber:presetNumber]; + self.activeFilterPredicate = [self combineFilterPresetPredicate:filterPresetPredicate + withSearchFilterPredicate:self.searchFieldPredicate]; [TTMFilterPredicates setActiveFilterPredicate:self.activeFilterPredicate]; [TTMFilterPredicates setActiveFilterPredicatePresetNumber:presetNumber]; self.activeFilterPredicateNumber = presetNumber; @@ -925,7 +951,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { } } // Check active filter menu item. - if ([menuItem.parentItem tag] == FILTERMENUTAG) { + if ([menuItem.parentItem tag] == FILTERMENUTAG) { if (menuItem.tag == self.activeFilterPredicateNumber) { [menuItem setState:NSOnState]; } else { @@ -1003,6 +1029,10 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N if ([keyPath isEqualToString:@"selection"]) { [self updateStatusBarText]; } + + if ([keyPath isEqualToString:@"searchFieldPredicate"]) { + [self reapplyActiveFilterPredicate]; + } } - (void)updateStatusBarText { diff --git a/TodoTxtMac/TTMPreferences.xib b/TodoTxtMac/TTMPreferences.xib index b7dd60d..81e217c 100644 --- a/TodoTxtMac/TTMPreferences.xib +++ b/TodoTxtMac/TTMPreferences.xib @@ -1,5 +1,5 @@ - + @@ -19,12 +19,12 @@ - + - + @@ -290,6 +290,9 @@ - + - + - - - - - - - - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - - - - - NSUnarchiveFromData - - - - - - - - - - - - - NSUnarchiveFromData - - - - - + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + + NSUnarchiveFromData + + + + + + + + + + + + + NSUnarchiveFromData + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + @@ -564,8 +526,11 @@ - + + + + @@ -580,8 +545,11 @@ - + + + + @@ -598,16 +566,11 @@ - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -652,8 +645,11 @@ - - + + + + @@ -681,8 +680,11 @@ - + + + + @@ -690,11 +692,25 @@ + + + + + + + + + + + + + + @@ -721,5 +737,235 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TodoTxtMac/TTMTableViewDelegate.h b/TodoTxtMac/TTMTableViewDelegate.h index c762c55..294d439 100644 --- a/TodoTxtMac/TTMTableViewDelegate.h +++ b/TodoTxtMac/TTMTableViewDelegate.h @@ -53,13 +53,4 @@ @property (nonatomic, retain) IBOutlet NSArrayController *arrayController; -#pragma mark - Attributed Text Methods - -/*! - * @method displayText: - * @abstract Creates the attributed string that colors and styles the task text in the table. - * @return An NSAttributedString that - */ -- (NSAttributedString*)displayText:(TTMTask*)task isSelected:(BOOL)selected; - @end diff --git a/TodoTxtMac/TTMTableViewDelegate.m b/TodoTxtMac/TTMTableViewDelegate.m index 89c7e02..2a0ec7b 100644 --- a/TodoTxtMac/TTMTableViewDelegate.m +++ b/TodoTxtMac/TTMTableViewDelegate.m @@ -51,12 +51,6 @@ @implementation TTMTableViewDelegate -static NSString * const ProjectPattern = @"(?<=^|\\s)(\\+[^\\s]+)"; -static NSString * const ContextPattern = @"(?<=^|\\s)(\\@[^\\s]+)"; -static NSString * const TagPattern = @"(?<=^|\\s)([:graph:]+:[:graph:]+)"; -static NSString * const FullDueDatePattern = @"(\\sdue:)((\\d{4})-(\\d{2})-(\\d{2}))"; -static NSString * const FullThresholdDatePattern = @"((^|\\s)t:)((\\d{4})-(\\d{2})-(\\d{2}))"; - #pragma mark - TableView Delegate Methods - (void)tableView:(NSTableView *)tableView @@ -65,128 +59,63 @@ - (void)tableView:(NSTableView *)tableView row:(NSInteger)row { // Apply the task's display format to the rawText cell. if ([[tableColumn identifier] isEqualToString:@"rawText"]) { - BOOL selected = ([tableView.selectedRowIndexes containsIndex:row]); TTMTask *task = [[self.arrayController arrangedObjects] objectAtIndex:row]; - if ([task.rawText length] > 0) { - [cell setAttributedStringValue:[self displayText:task isSelected:selected]]; + if (nil == task || task.isBlank) { + return; } - } -} - -#pragma mark - Attributed Text Methods -- (NSAttributedString*)displayText:(TTMTask*)task - isSelected:(BOOL)selected { - NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:task.rawText]; - NSRange fullStringRange = NSMakeRange(0, [as length]); - - // Apply strikethrough and light gray color to completed tasks when they are displayed - // in the tableView. - if (task.isCompleted) { - [as addAttribute:NSStrikethroughStyleAttributeName - value:(NSNumber*)kCFBooleanTrue - range:fullStringRange]; - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor lightGrayColor] - range:fullStringRange]; - return as; - } - - // Apply boldface to the task priority. - if (task.isPrioritized) { - [as applyFontTraits:NSBoldFontMask range:NSMakeRange(0, 3)]; - } - - // Only change colors if row is not selected and user wants to see highlight colors. - if (!selected && [[NSUserDefaults standardUserDefaults] - boolForKey:@"useHighlightColorsInTaskList"]) { - // Get the user's preferred highlight colors or the defaults. + BOOL selected = ([tableView.selectedRowIndexes containsIndex:row]); + BOOL useHighlightColorsInTaskList = [[NSUserDefaults standardUserDefaults] + boolForKey:@"useHighlightColorsInTaskList"]; + NSColor *completedColor = [NSColor lightGrayColor]; NSColor *dueTodayColor = ([[NSUserDefaults standardUserDefaults] boolForKey:@"useCustomColorForDueTodayTasks"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"dueTodayColor"] : [NSColor redColor]; NSColor *overdueColor = ([[NSUserDefaults standardUserDefaults] - boolForKey:@"useCustomColorForOverdueTasks"]) ? + boolForKey:@"useCustomColorForOverdueTasks"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"overdueColor"] : [NSColor purpleColor]; - NSColor *projectsColor = ([[NSUserDefaults standardUserDefaults] + NSColor *projectColor = ([[NSUserDefaults standardUserDefaults] boolForKey:@"useCustomColorForProjects"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"projectColor"] : [NSColor darkGrayColor]; - NSColor *contextsColor = ([[NSUserDefaults standardUserDefaults] + NSColor *contextColor = ([[NSUserDefaults standardUserDefaults] boolForKey:@"useCustomColorForContexts"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"contextColor"] : [NSColor darkGrayColor]; NSColor *tagColor = ([[NSUserDefaults standardUserDefaults] - boolForKey:@"useCustomColorForTags"]) ? + boolForKey:@"useCustomColorForTags"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"tagColor"] : [NSColor darkGrayColor]; NSColor *dueDateColor = ([[NSUserDefaults standardUserDefaults] - boolForKey:@"useCustomColorForDueDates"]) ? + boolForKey:@"useCustomColorForDueDates"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"dueDateColor"] : [NSColor darkGrayColor]; NSColor *thresholdDateColor = ([[NSUserDefaults standardUserDefaults] - boolForKey:@"useCustomColorForThresholdDates"]) ? + boolForKey:@"useCustomColorForThresholdDates"]) ? [[NSUserDefaults standardUserDefaults] colorForKey:@"thresholdDateColor"] : [NSColor darkGrayColor]; - - // Color due texts. - if (task.dueState == DueToday) { - [as addAttribute:NSForegroundColorAttributeName - value:dueTodayColor - range:fullStringRange]; - } - - // Color overdue texts. - if (task.dueState == Overdue) { - [as addAttribute:NSForegroundColorAttributeName - value:overdueColor - range:fullStringRange]; - } + NSColor *creationDateColor = ([[NSUserDefaults standardUserDefaults] + boolForKey:@"useCustomColorForCreationDates"]) ? + [[NSUserDefaults standardUserDefaults] colorForKey:@"creationDateColor"] : + [NSColor darkGrayColor]; - // Color projects. - NSArray* matches = [task.rawText matchesWithDetails:RX(ProjectPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:projectsColor - range:match.range]; - } - - // Color contexts. - matches = [task.rawText matchesWithDetails:RX(ContextPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:contextsColor - range:match.range]; - } + NSAttributedString *as = [task displayText:selected + useHighlightColorsInTaskList:useHighlightColorsInTaskList + completedColor:completedColor + dueTodayColor:dueTodayColor + overdueColor:overdueColor + projectColor:projectColor + contextColor:contextColor + tagColor:tagColor + dueDateColor:dueDateColor + thresholdDateColor:thresholdDateColor + creationDateColor:creationDateColor]; - // Color tags. - matches = [task.rawText matchesWithDetails:RX(TagPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:tagColor - range:match.range]; - } - - // Color due dates. - matches = [task.rawText matchesWithDetails:RX(FullDueDatePattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:dueDateColor - range:match.range]; - } - - // Color threshold dates. - matches = [task.rawText matchesWithDetails:RX(FullThresholdDatePattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:thresholdDateColor - range:match.range]; - } + [cell setAttributedStringValue:as]; } - - return as; } @end diff --git a/TodoTxtMac/TTMTask.h b/TodoTxtMac/TTMTask.h index 56c98bf..5a1b2aa 100644 --- a/TodoTxtMac/TTMTask.h +++ b/TodoTxtMac/TTMTask.h @@ -163,10 +163,19 @@ typedef enum : NSUInteger { * @abstact Returns the task's raw text as a formatted string for display. * @return Returns an attributed string to be used for display in the user interface. * @discussion For good MVC compartmentalization, this method does not access the application's - * user defaults. To customize the display text's colors and styles based on user defaults, - * write a similar method to displayText: in a controller class and call that instead. + * user defaults. Therefore, all color options are passed to this method. */ -- (NSAttributedString*)displayText; +- (NSAttributedString*)displayText:(BOOL)selected + useHighlightColorsInTaskList:(BOOL)useHighlightColorsInTaskList + completedColor:(NSColor*)completedColor + dueTodayColor:(NSColor*)dueTodayColor + overdueColor:(NSColor*)overdueColor + projectColor:(NSColor*)projectColor + contextColor:(NSColor*)contextColor + tagColor:(NSColor*)tagColor + dueDateColor:(NSColor*)dueDateColor + thresholdDateColor:(NSColor*)thresholdDateColor + creationDateColor:(NSColor*)creationDateColor; #pragma mark - Append and Prepend Methods @@ -225,20 +234,20 @@ typedef enum : NSUInteger { - (void)removeThresholdDate; /*! - * @method incrementThresholdDay; + * @method incrementThresholdDate: * @abstract Increases threshold day by a specified number of days. - * Sets threshold date to today if there is no threshold date. + * Sets threshold date to tomorrow if there is no threshold date. * @param Number of days to add to the task threshold date. */ -- (void)incrementThresholdDay:(NSInteger)days; +- (void)incrementThresholdDate:(NSInteger)days; /*! - * @method decrementThresholdDay; + * @method decrementThresholdDate: * @abstract Decreases threshold day by a specified number of days. - * Sets threshold date to today if there is no threshold date. + * Sets threshold date to yesterday if there is no threshold date. * @param Number of days to subtract to the task threshold date. */ -- (void)decrementThresholdDay:(NSInteger)days; +- (void)decrementThresholdDate:(NSInteger)days; /*! * @method getThresholdState: @@ -318,6 +327,22 @@ typedef enum : NSUInteger { */ - (void)postponeTask:(NSInteger)days; +/*! + * @method incrementDueDate: + * @abstract Increases due date by a specified number of days. + * Sets due date to tomorrow if there is no threshold date. + * @param Number of days to add to the task due date. + */ +- (void)incrementDueDate:(NSInteger)days; + +/*! + * @method decrementDueDate: + * @abstract Decreases due date by a specified number of days. + * Sets due date to yesterday if there is no threshold date. + * @param Number of days to subtract to the task due date. + */ +- (void)decrementDueDate:(NSInteger)days; + /*! * @method setDueDate: * @abstract Sets the due date. diff --git a/TodoTxtMac/TTMTask.m b/TodoTxtMac/TTMTask.m index f06d3e9..9b499ba 100644 --- a/TodoTxtMac/TTMTask.m +++ b/TodoTxtMac/TTMTask.m @@ -47,6 +47,7 @@ #import "TTMTask.h" #import "RegExCategories.h" #import "TTMDateUtility.h" +#import "NSMutableAttributableString+ColorRegExMatches.h" @implementation TTMTask @@ -55,16 +56,18 @@ @implementation TTMTask // define constants for regular expressions static NSString * const LineBreakPattern = @"(\\r|\\n)"; static NSString * const CompletedPattern = @"^x\\s((\\d{4})-(\\d{2})-(\\d{2}))\\s"; -static NSString * const CompletionDatePattern = @"(?<=^x\\s)((\\d{4})-(\\d{2})-(\\d{2}))"; +static NSString * const CompletionDatePattern = @"(?<=^x\\s)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; static NSString * const PriorityTextPattern = @"^(\\([A-Z]\\)\\s)"; static NSString * const CreationDatePatternIncomplete = - @"(?<=^|\\([A-Z]\\)\\s)((\\d{4})-(\\d{2})-(\\d{2}))"; + @"(?<=^|\\([A-Z]\\)\\s)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; static NSString * const CreationDatePatternCompleted = - @"(?<=^x\\s((\\d{4})-(\\d{2})-(\\d{2}))\\s)((\\d{4})-(\\d{2})-(\\d{2}))"; -static NSString * const DueDatePattern = @"(?<=due:)((\\d{4})-(\\d{2})-(\\d{2}))"; -static NSString * const FullDueDatePattern = @"((^|\\s)due:)((\\d{4})-(\\d{2})-(\\d{2}))"; -static NSString * const ThresholdDatePattern = @"(?<=t:)((\\d{4})-(\\d{2})-(\\d{2}))"; -static NSString * const FullThresholdDatePattern = @"((^|\\s)t:)((\\d{4})-(\\d{2})-(\\d{2}))"; + @"(?<=^x\\s((\\d{4})-(\\d{2})-(\\d{2}))\\s)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; +static NSString * const DueDatePattern = @"(?<=(^|\\s)due:)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; +static NSString * const FullDueDatePatternMiddleOrEnd = @"((\\s)due:)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; +static NSString * const FullDueDatePatternBeginning = @"^due:((\\d{4})-(\\d{2})-(\\d{2}))\\s?|$"; +static NSString * const ThresholdDatePattern = @"(?<=(^|\\s)t:)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; +static NSString * const FullThresholdDatePatternMiddleOrEnd = @"((\\s)t:)((\\d{4})-(\\d{2})-(\\d{2}))(?=\\s|$)"; +static NSString * const FullThresholdDatePatternBeginning = @"^t:((\\d{4})-(\\d{2})-(\\d{2}))\\s?|$"; static NSString * const ProjectPattern = @"(?<=^|\\s)(\\+[^\\s]+)"; static NSString * const ContextPattern = @"(?<=^|\\s)(\\@[^\\s]+)"; static NSString * const TagPattern = @"(?<=^|\\s)([:graph:]+:[:graph:]+)"; @@ -137,7 +140,7 @@ - (void)setRawText:(NSString*)rawText { _isCompleted = NO; _isPrioritized = NO; _priorityText = @""; - _priority = ' '; + _priority = '~'; _contexts = @""; _contextsArray = nil; _projects = @""; @@ -158,10 +161,21 @@ - (void)setRawText:(NSString*)rawText { // set properties for non-blank strings _isBlank = NO; - _isCompleted = [_rawText isMatch:RX(CompletedPattern)]; - _isPrioritized = [_rawText isMatch:RX(PriorityTextPattern)]; + + // completion date + _completionDateText = [_rawText firstMatch:RX(CompletionDatePattern)]; + // Set completion date to the high date (9999-12-31) to ensure that tasks with no + // completion date are sorted after tasks with a due date. + NSDate *newCompletionDate = (_completionDateText == nil) ? + [TTMDateUtility convertStringToDate:@"9999-12-31"] : + [TTMDateUtility convertStringToDate:_completionDateText]; + _completionDate = (newCompletionDate == nil) ? + [TTMDateUtility convertStringToDate:@"9999-12-31"] : + newCompletionDate; + _isCompleted = [_rawText isMatch:RX(CompletedPattern)] && (newCompletionDate != nil); // priority + _isPrioritized = [_rawText isMatch:RX(PriorityTextPattern)]; _fullPriorityText = [_rawText firstMatch:RX(PriorityTextPattern)]; NSRange range = {.location = 1, .length = 1}; _priorityText = [_fullPriorityText substringWithRange:range]; @@ -181,39 +195,49 @@ - (void)setRawText:(NSString*)rawText { _contexts = [_contextsArray componentsJoinedByString:@", "]; _hasContexts = (_contextsArray.count > 0); - // completion date - _completionDateText = [_rawText firstMatch:RX(CompletionDatePattern)]; - // Set completion date to the high date (9999-12-31) to ensure that tasks with no - // completion date are sorted after tasks with a due date. - _completionDate = (_completionDateText == nil) ? - [TTMDateUtility convertStringToDate:@"9999-12-31"] : - [TTMDateUtility convertStringToDate:_completionDateText]; - // due date _dueDateText = [_rawText firstMatch:RX(DueDatePattern)]; // Set due date to the high date (9999-12-31) to ensure that tasks with no due date // are sorted after tasks with a due date. - _dueDate = (_dueDateText == nil) ? + NSDate *newDueDate = (_dueDateText == nil) ? [TTMDateUtility convertStringToDate:@"9999-12-31"] : [TTMDateUtility convertStringToDate:_dueDateText]; - + if (newDueDate == nil) { + _dueDate = [TTMDateUtility convertStringToDate:@"9999-12-31"]; + _dueDateText = @""; + } else { + _dueDate = newDueDate; + } + // creation date _creationDateText = _isCompleted ? [_rawText firstMatch:RX(CreationDatePatternCompleted)] : [_rawText firstMatch:RX(CreationDatePatternIncomplete)]; // Set creation date to the high date (9999-12-31) to ensure that tasks with no // creation date are sorted after tasks with a creation date. - _creationDate = (_creationDateText == nil) ? + NSDate *newCreationDate = (_creationDateText == nil) ? [TTMDateUtility convertStringToDate:@"9999-12-31"] : [TTMDateUtility convertStringToDate:_creationDateText]; + if (newCreationDate == nil) { + _creationDate = [TTMDateUtility convertStringToDate:@"9999-12-31"]; + _creationDateText = @""; + } else { + _creationDate = newCreationDate; + } // threshold date _thresholdDateText = [_rawText firstMatch:RX(ThresholdDatePattern)]; - // Set threshold date to the high date (1900-01-01) to ensure that tasks with no + // Set threshold date to the low date (1900-01-01) to ensure that tasks with no // threshold date are properly sorted/displated when filtered. - _thresholdDate = (_thresholdDateText == nil) ? + NSDate *newThresholdDate = (_thresholdDateText == nil) ? [TTMDateUtility convertStringToDate:@"1900-01-01"] : [TTMDateUtility convertStringToDate:_thresholdDateText]; + if (newThresholdDate == nil) { + _thresholdDate = [TTMDateUtility convertStringToDate:@"1900-01-01"]; + _thresholdDateText = @""; + } else { + _thresholdDate = newThresholdDate; + } // due state (past due, due today, not due) _dueState = [self getDueState]; @@ -226,18 +250,30 @@ - (NSString*)rawText { return _rawText; } -- (NSAttributedString*)displayText { +- (NSAttributedString*)displayText:(BOOL)selected + useHighlightColorsInTaskList:(BOOL)useHighlightColorsInTaskList + completedColor:(NSColor*)completedColor + dueTodayColor:(NSColor*)dueTodayColor + overdueColor:(NSColor*)overdueColor + projectColor:(NSColor*)projectColor + contextColor:(NSColor*)contextColor + tagColor:(NSColor*)tagColor + dueDateColor:(NSColor*)dueDateColor + thresholdDateColor:(NSColor*)thresholdDateColor + creationDateColor:(NSColor*)creationDateColor { NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:self.rawText]; NSRange fullStringRange = NSMakeRange(0, [as length]); + // Apply strikethrough and light gray color to completed tasks when they are displayed // in the tableView. if (self.isCompleted) { [as addAttribute:NSStrikethroughStyleAttributeName - value:(NSNumber *)kCFBooleanTrue + value:(NSNumber*)kCFBooleanTrue range:fullStringRange]; [as addAttribute:NSForegroundColorAttributeName value:[NSColor lightGrayColor] range:fullStringRange]; + return as; } // Apply boldface to the task priority. @@ -245,59 +281,40 @@ - (NSAttributedString*)displayText { [as applyFontTraits:NSBoldFontMask range:NSMakeRange(0, 3)]; } - // Mark due texts in red. + // Only change colors if row is not selected and user wants to see highlight colors. + if (selected || !useHighlightColorsInTaskList) { + return as; + } + + // Color due texts. if (self.dueState == DueToday) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor redColor] - range:fullStringRange]; + [as applyColorToFullStringRange:dueTodayColor]; } - // Mark overdue texts in purple. + // Color overdue texts. if (self.dueState == Overdue) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor purpleColor] - range:fullStringRange]; + [as applyColorToFullStringRange:overdueColor]; } - // Highlight projects. - NSArray* matches = [self.rawText matchesWithDetails:RX(ProjectPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor darkGrayColor] - range:match.range]; - } + // Color projects. + [as applyColor:projectColor toRegexPatternMatches:ProjectPattern]; - // Highlight contexts. - matches = [self.rawText matchesWithDetails:RX(ContextPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor darkGrayColor] - range:match.range]; - } + // Color contexts. + [as applyColor:contextColor toRegexPatternMatches:ContextPattern]; - // Highlight tags. - matches = [self.rawText matchesWithDetails:RX(TagPattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor darkGrayColor] - range:match.range]; - } - - // Highlight due dates. - matches = [self.rawText matchesWithDetails:RX(FullDueDatePattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor darkGrayColor] - range:match.range]; - } + // Color tags. + [as applyColor:tagColor toRegexPatternMatches:TagPattern]; + + // Color due dates. + [as applyColor:dueDateColor toRegexPatternMatches:FullDueDatePatternBeginning]; + [as applyColor:dueDateColor toRegexPatternMatches:FullDueDatePatternMiddleOrEnd]; + + // Color threshold dates. + [as applyColor:thresholdDateColor toRegexPatternMatches:FullThresholdDatePatternBeginning]; + [as applyColor:thresholdDateColor toRegexPatternMatches:FullThresholdDatePatternMiddleOrEnd]; - // Highlight threshold dates. - matches = [self.rawText matchesWithDetails:RX(FullThresholdDatePattern)]; - for (RxMatch *match in matches) { - [as addAttribute:NSForegroundColorAttributeName - value:[NSColor darkGrayColor] - range:match.range]; - } + // Color creation dates (incomplete tasks only). + [as applyColor:creationDateColor toRegexPatternMatches:CreationDatePatternIncomplete]; return as; } @@ -305,32 +322,73 @@ - (NSAttributedString*)displayText { #pragma mark - Append and Prepend Methods - (void)appendText:(NSString*)textToAppend { - NSString *newRawText = [self.rawText - stringByAppendingFormat:@"%c%@", ' ', textToAppend]; - [self setRawText:newRawText]; + if (self.isBlank) { + self.rawText = textToAppend; + return; + } + + self.rawText = [self.rawText stringByAppendingFormat:@"%c%@", ' ', textToAppend]; } - (void)prependText:(NSString*)textToPrepend { - NSString *separator = @" "; - NSString *rawTextRemainder = self.rawText; - NSArray *stringComponents = nil; - NSString *trimmedPriorityText = [self.fullPriorityText substringToIndex:3]; - - if (self.isPrioritized && self.creationDateText != nil) { - rawTextRemainder = [self.rawText substringFromIndex:15]; - stringComponents = @[trimmedPriorityText, self.creationDateText, - textToPrepend, rawTextRemainder ]; - } else if (self.isPrioritized && self.creationDateText == nil) { - rawTextRemainder = [self.rawText substringFromIndex:4]; - stringComponents = @[trimmedPriorityText, textToPrepend, rawTextRemainder]; - } else if (self.creationDateText != nil) { - rawTextRemainder = [self.rawText substringFromIndex:11]; - stringComponents = @[self.creationDateText, textToPrepend, rawTextRemainder]; + if (self.isBlank) { + self.rawText = textToPrepend; + return; + } + + NSUInteger insertionIndex; + + if (self.isCompleted && [self.creationDateText length] > 0) { + // For completed tasks with creation date, prepend text after the completion date and creation date + insertionIndex = 24; + } else if (self.isCompleted && [self.creationDateText length] == 0) { + // For completed tasks with no creation date, prepend text after the completion date + insertionIndex = 13; + } else if (self.isPrioritized && [self.creationDateText length] > 0) { + // For incomplete tasks with a creation date, prepend text after priority and creation date. + insertionIndex = 15; + } else if (self.isPrioritized && [self.creationDateText length] == 0) { + // For incomplete tasks with a priority and no creation date, prepend text after priority. + insertionIndex = 4; + } else if ([self.creationDateText length] > 0) { + // For incomplete tasks with a creation date, prepend text after creation date. + insertionIndex = 11; } else { - rawTextRemainder = self.rawText; - stringComponents = @[textToPrepend, rawTextRemainder]; + // For all other types of tasks, prepend text to the beginning of the task. + insertionIndex = 0; + } + + if (insertionIndex == 0) + { + self.rawText = [NSString stringWithFormat:@"%@%@%@", textToPrepend, @" ", self.rawText]; + return; } - [self setRawText:[stringComponents componentsJoinedByString:separator]]; + + NSString *rawTextPrefix = [self.rawText substringWithRange:NSMakeRange(0, insertionIndex - 1)]; + NSString *rawTextRemainder = [self.rawText substringFromIndex:insertionIndex]; + NSArray *rawTextComponents = @[rawTextPrefix, textToPrepend, rawTextRemainder]; + self.RawText = [rawTextComponents componentsJoinedByString:@" "]; + +// NSString *separator = @" "; +// NSString *rawTextRemainder = self.rawText; +// NSArray *stringComponents = nil; +// NSString *trimmedPriorityText = [self.fullPriorityText substringToIndex:3]; +// +// if (self.isPrioritized && self.creationDateText != nil) { +// rawTextRemainder = [self.rawText substringFromIndex:15]; +// stringComponents = @[trimmedPriorityText, self.creationDateText, +// textToPrepend, rawTextRemainder ]; +// } else if (self.isPrioritized && self.creationDateText == nil) { +// rawTextRemainder = [self.rawText substringFromIndex:4]; +// stringComponents = @[trimmedPriorityText, textToPrepend, rawTextRemainder]; +// } else if (self.creationDateText != nil) { +// rawTextRemainder = [self.rawText substringFromIndex:11]; +// stringComponents = @[self.creationDateText, textToPrepend, rawTextRemainder]; +// } else { +// rawTextRemainder = self.rawText; +// stringComponents = @[textToPrepend, rawTextRemainder]; +// } +// self.rawText = [stringComponents componentsJoinedByString:separator]; } #pragma Find/replace Method @@ -380,11 +438,11 @@ - (void)removeThresholdDate { return; } - self.rawText = [[self.rawText replace:RX(FullThresholdDatePattern) with:@""] - stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + NSString *newRawText = [self.rawText replace:RX(FullThresholdDatePatternBeginning) with:@""]; + self.rawText = [newRawText replace:RX(FullThresholdDatePatternMiddleOrEnd) with:@""]; } -- (void)incrementThresholdDay:(NSInteger)days { +- (void)incrementThresholdDate:(NSInteger)days { // Blank tasks don't get updated threshold dates. if (self.isBlank) { return; @@ -403,11 +461,11 @@ - (void)incrementThresholdDay:(NSInteger)days { // Add days to that date to create the new due date. NSDate *newThresholdDate = [TTMDateUtility addDays:days toDate:oldThresholdDate]; - [self setThresholdDate:newThresholdDate]; + self.thresholdDate = newThresholdDate; } -- (void)decrementThresholdDay:(NSInteger)days { - [self incrementThresholdDay:(-1 * days)]; +- (void)decrementThresholdDate:(NSInteger)days { + [self incrementThresholdDate:(-1 * days)]; } - (TTMThresholdState)getThresholdState { @@ -447,9 +505,9 @@ - (void)setPriority:(unichar)priority { if (self.isPrioritized) { NSRange oldPriority = [self.rawText rangeOfString:self.fullPriorityText]; if (NSNotFound != oldPriority.location) { - self.rawText = - [self.rawText stringByReplacingCharactersInRange:oldPriority - withString:[NSString stringWithFormat:@"%c%c%c%c", '(', priority, ')', ' ']]; + self.rawText = [self.rawText stringByReplacingCharactersInRange:oldPriority + withString:[NSString stringWithFormat: + @"%c%c%c%c", '(', priority, ')', ' ']]; } } else { self.rawText = [NSString stringWithFormat:@"%c%c%c %@", '(', priority, ')', self.rawText]; @@ -474,7 +532,6 @@ - (void)increasePriority { // increase priority of task (e.g. 'B' - 1 = 'A') self.priority = self.priority - 1; -// [self setPriority:(self.priority - 1)]; } - (void)decreasePriority { @@ -496,7 +553,6 @@ - (void)decreasePriority { // decrease priority of task (e.g. 'A' + 1 = 'B') self.priority = self.priority + 1; -// [self setPriority:(self.priority + 1)]; } - (void)removePriority { @@ -530,7 +586,7 @@ - (void)markComplete { [TTMDateUtility todayAsString], ' ', rawTextWithoutPriority]; // Update the task's raw text. - [self setRawText:newRawText]; + self.rawText = newRawText; } - (void)markIncomplete { @@ -541,7 +597,7 @@ - (void)markIncomplete { } // Remove the completed task prepended substring and update all class properties. - [self setRawText:[RX(CompletedPattern) replace:self.rawText with:@""]]; + self.rawText = [RX(CompletedPattern) replace:self.rawText with:@""]; } - (void)toggleCompletionStatus { @@ -570,11 +626,25 @@ - (void)postponeTask:(NSInteger)daysToPostpone { // Add days to that date to create the new due date. NSDate *newDueDate = [TTMDateUtility addDays:daysToPostpone toDate:oldDueDate]; + + self.dueDate = newDueDate; +} + +- (void)incrementDueDate:(NSInteger)days { + [self postponeTask:days]; +} + +- (void)decrementDueDate:(NSInteger)days { + [self postponeTask:(-1 * days)]; - [self setDueDate:newDueDate]; } - (void)setDueDate:(NSDate *)dueDate { + // Blank tasks don't get due dates. + if (self.isBlank) { + return; + } + NSString *newDueDateText = [TTMDateUtility convertDateToString:dueDate]; // If the item has a due date, exchange the current due date with the new. // Else if the item does not have a due date, append the new due date to the task. @@ -588,9 +658,9 @@ - (void)removeDueDate { if (self.isBlank || !self.dueDate) { return; } - - self.rawText = [[self.rawText replace:RX(FullDueDatePattern) with:@""] - stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + NSString *newRawText = [self.rawText replace:RX(FullDueDatePatternBeginning) with:@""]; + self.rawText = [newRawText replace:RX(FullDueDatePatternMiddleOrEnd) with:@""]; } @end diff --git a/TodoTxtMac/TodoTxtMac-Info.plist b/TodoTxtMac/TodoTxtMac-Info.plist index 134a037..1f2276e 100644 --- a/TodoTxtMac/TodoTxtMac-Info.plist +++ b/TodoTxtMac/TodoTxtMac-Info.plist @@ -38,11 +38,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.0 + 1.5.0 CFBundleSignature ???? CFBundleVersion - 1.4.0 + 1.5.0 LSApplicationCategoryType public.app-category.productivity LSMinimumSystemVersion diff --git a/TodoTxtMacTests/TTMDateUtility_UnitTests.m b/TodoTxtMacTests/TTMDateUtility_UnitTests.m new file mode 100644 index 0000000..518cff3 --- /dev/null +++ b/TodoTxtMacTests/TTMDateUtility_UnitTests.m @@ -0,0 +1,101 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMDateUtility.h" + +@interface TTMDateUtility_UnitTests : XCTestCase + +@end + +@implementation TTMDateUtility_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testDateConversions { + NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; + NSLog(@"firstDate: %@", firstDate); + NSString *firstDateString = [TTMDateUtility convertDateToString:firstDate]; + NSLog(@"firstDateString: %@", firstDateString); + NSDate *secondDate = [TTMDateUtility convertStringToDate:firstDateString]; + NSLog(@"secondDate: %@", secondDate); + XCTAssertEqualObjects(firstDate, secondDate); +} + +- (void)testAddDaysToDate { + NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; + NSDate *secondDate = [TTMDateUtility convertStringToDate:@"2014-01-02"]; + NSDate *firstDateModified = [TTMDateUtility addDays:1 toDate:firstDate]; + NSLog(@"new date: %@", firstDateModified); + XCTAssertEqualObjects(firstDateModified, secondDate); +} + +- (void)testAddDaysToDate_DayLightSavingsTimeUSStart2015 { + NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2015-03-08"]; + NSDate *secondDate = [TTMDateUtility convertStringToDate:@"2015-03-09"]; + NSDate *firstDateModified = [TTMDateUtility addDays:1 toDate:firstDate]; + NSLog(@"new date: %@", firstDateModified); + XCTAssertEqualObjects(firstDateModified, secondDate); +} + +- (void)testAddNegativeDaysToDate { + NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-02"]; + NSDate *secondDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; + NSDate *firstDateModified = [TTMDateUtility addDays:-1 toDate:firstDate]; + NSLog(@"new date: %@", firstDateModified); + XCTAssertEqualObjects(firstDateModified, secondDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_AppendText_UnitTests.m b/TodoTxtMacTests/TTMTask_AppendText_UnitTests.m new file mode 100644 index 0000000..aa80698 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_AppendText_UnitTests.m @@ -0,0 +1,87 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_AppendText_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSString *textToAppend; + +@end + +@implementation TTMTask_AppendText_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.textToAppend = @"[text to append]"; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_AppendText_WhenTaskIsNotBlank_ShouldAppendTextToEnd { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task appendText:self.textToAppend]; + NSString *expectedRawText = @"pick up groceries [text to append]"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_AppendText_WhenTaskIsBlank_ShouldAppendTextToEnd { + NSString *rawText = @""; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task appendText:self.textToAppend]; + XCTAssertEqualObjects(self.textToAppend, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_CompletionDate_UnitTests.m b/TodoTxtMacTests/TTMTask_CompletionDate_UnitTests.m new file mode 100644 index 0000000..281c9c7 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_CompletionDate_UnitTests.m @@ -0,0 +1,137 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_CompletionDate_UnitTests : XCTestCase + +@property NSString *rawText; +@property NSUInteger taskId; +@property NSDate *completionDate; +@property NSDate *highDate; + +@end + +@implementation TTMTask_CompletionDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.rawText = @"pick up groceries"; + self.taskId = 10; + self.completionDate = [TTMDateUtility convertStringToDate:@"2020-01-31"]; + self.highDate = [TTMDateUtility convertStringToDate:@"9999-12-31"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_CompletionDate_WhenCompleted_ShouldBeCompletionDate { + NSString *rawText = @"x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.completionDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenNotCompleted_ShouldBeHighDate { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedFormatHasCapitalX_ShouldBeHighDate { + NSString *rawText = @"X 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedFormatHasNoDate_ShouldBeHighDate { + NSString *rawText = @"x pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedDateHasNoLeadingSpace_ShouldBeHighDate { + NSString *rawText = @"x2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedDateHasNoTrailingSpace_ShouldBeHighDate { + NSString *rawText = @"x 2020-01-31pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedDateHasTwoLeadingSpaces_ShouldBeHighDate { + NSString *rawText = @"x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedDateMonthInvalid_ShouldBeHighDate { + NSString *rawText = @"x 2020-13-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedDateDayInvalid_ShouldBeHighDate { + NSString *rawText = @"x 2020-12-32 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +- (void)test_CompletionDate_WhenCompletedFormatHasLeadingSpace_ShouldBeHighDate { + NSString *rawText = @" x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.completionDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_Contexts_UnitTests.m b/TodoTxtMacTests/TTMTask_Contexts_UnitTests.m new file mode 100644 index 0000000..cc543fd --- /dev/null +++ b/TodoTxtMacTests/TTMTask_Contexts_UnitTests.m @@ -0,0 +1,94 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_Contexts_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_Contexts_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_contexts_WhenTaskHasOneProject_ShouldBeOneProject { + NSString *rawText = @"pick up groceries @Chores"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"@Chores", task.contexts); +} + +- (void)test_contexts_WhenTaskHasMultipleContexts_ShouldBeAllcontextsAlphabetized { + NSString *rawText = @"pick up groceries @Shopping @Chores @Errands"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"@Chores, @Errands, @Shopping", task.contexts); +} + +- (void)test_contexts_WhenTaskHasMultipleContextsWithOddPunctuation_ShouldBeAllcontextsAlphabetized { + NSString *rawText = @"pick up groceries @Shopping; @Chores@Personal @-Errands-"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"@-Errands-, @Chores@Personal, @Shopping;", task.contexts); +} + +- (void)test_Projects_WhenTaskHasNoContexts_ShouldBeEmptyString { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"", task.contexts); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_CreationDate_UnitTests.m b/TodoTxtMacTests/TTMTask_CreationDate_UnitTests.m new file mode 100644 index 0000000..d0cde2d --- /dev/null +++ b/TodoTxtMacTests/TTMTask_CreationDate_UnitTests.m @@ -0,0 +1,141 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_CreationDate_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSDate *creationDate; +@property NSDate *highDate; + +@end + +@implementation TTMTask_CreationDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.creationDate = [TTMDateUtility convertStringToDate:@"2020-01-01"]; + self.highDate = [TTMDateUtility convertStringToDate:@"9999-12-31"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_CreationDate_WhenIncompleteWithCreationDateAndNoPriority_ShouldBeCreationDate { + NSString *rawText = @"2020-01-01 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.creationDate, task.creationDate); +} + +- (void)test_CreationDate_WhenIncompleteWithCreationDateAndPriority_ShouldBeCreationDate { + NSString *rawText = @"(A) 2020-01-01 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.creationDate, task.creationDate); +} + +- (void)test_CreationDate_WhenIncompleteWithNoCreationDate_ShouldBeHighDate { + NSString *rawText = @"(A) test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_CreationDate_WhenCompleteWithCreationDate_ShouldBeCreationDate { + NSString *rawText = @"x 2013-12-31 2020-01-01 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.creationDate, task.creationDate); +} + +- (void)test_CreationDate_WhenCompleteWithCreationDateWithNoLeadingSpace_ShouldBeHighDate { + NSString *rawText = @"x 2020-12-312020-01-01 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_CreationDate_WhenCompleteWithCreationDateWithNoTrailingSpace_ShouldBeHighDate { + NSString *rawText = @"x 2020-01-01 2020-01-01test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_CreationDate_WhenIncompleteWithCreationDateWithNoLeadingSpace_ShouldBeHighDate { + NSString *rawText = @"(A)2020-01-01 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_CreationDate_WhenIncompleteWithCreationDateWithNoTrailingSpace_ShouldBeHighDate { + NSString *rawText = @"(A) 2020-01-01test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_CreationDate_WhenCompleteWithNoCreationDate_ShouldBeHighDate { + NSString *rawText = @"x 2020-12-31 test task due:2020-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_DueDate_WhenCreationDateMonthInvalid_ShouldBeHighDate { + NSString *rawText = @"(A) 9999-13-31 test task +Project1"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +- (void)test_DueDate_WhenCreationDateDayInvalid_ShouldBeHighDate { + NSString *rawText = @"(A) 9999-12-32 test task due:9999-12-32 +Project1"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.highDate, task.creationDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_DecreasePriority_UnitTests.m b/TodoTxtMacTests/TTMTask_DecreasePriority_UnitTests.m new file mode 100644 index 0000000..4b3b876 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_DecreasePriority_UnitTests.m @@ -0,0 +1,107 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_DecreasePriority_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_DecreasePriority_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_DecreasePriority_WhenPriorityIsC_ShouldSetPriorityToD { + NSString *rawText = @"(C) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decreasePriority]; + NSString *expectedRawText = @"(D) pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecreasePriority_WhenPriorityIsZ_ShouldDoNothing { + NSString *rawText = @"(Z) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decreasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +- (void)test_DecreasePriority_WhenNoPriority_ShouldSetPriorityToA { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decreasePriority]; + NSString *expectedRawText = @"(A) pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenTaskIsComplete_ShouldDoNothing { + NSString *rawText = @"x 2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decreasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenTaskIsBlank_ShouldDoNothing { + NSString *rawText = @""; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decreasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_DecrementDueDate_UnitTests.m b/TodoTxtMacTests/TTMTask_DecrementDueDate_UnitTests.m new file mode 100644 index 0000000..c376ee6 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_DecrementDueDate_UnitTests.m @@ -0,0 +1,142 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_DecrementDueDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_DecrementDueDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_DecrementDueDate_ByOneDayWhenTaskHasDueDateAtEnd_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByOneDayWhenTaskHasDueDateInMiddle_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByOneDayWhenTaskHasDueDateAtBeginning_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:1]; + NSString *expectedRawText = @"due:2020-01-30 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfTomorrow { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:1]; + NSDate *yesterday = [TTMDateUtility addDays:-1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:yesterday]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByNegativeOneDayWhenTaskHasDueDateAtEnd_ShouldDIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByNegativeOneDayWhenTaskHasDueDateInMiddle_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} +- (void)test_DecrementDueDate_ByNegativeOneDayWhenTaskHasDueDateAtBeginning_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:-1]; + NSString *expectedRawText = @"due:2020-02-01 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementDueDate_ByNegativeOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfTomorrow { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementDueDate:-1]; + NSDate *tomorrow = [TTMDateUtility addDays:1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:tomorrow]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_DecrementThresholdDate_UnitTests.m b/TodoTxtMacTests/TTMTask_DecrementThresholdDate_UnitTests.m new file mode 100644 index 0000000..4a1fe15 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_DecrementThresholdDate_UnitTests.m @@ -0,0 +1,91 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_DecrementThresholdDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_DecrementThresholdDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_DecrementThresholdDate_WhenTaskHasNoThresholdDate_ShouldIncrementThresholdDateByOneDay { + NSString *rawText = @"pick up groceries t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementThresholdDate:1]; + NSString *expectedRawText = @"pick up groceries t:2020-01-30"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_DecrementThresholdDate_WhenTaskHasNoThresholdDate_ShouldAppendThresholdDateOfYesterday { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task decrementThresholdDate:1]; + NSDate *yesterday = [TTMDateUtility addDays:-1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" t:", + [TTMDateUtility convertDateToString:yesterday]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_DueDate_UnitTests.m b/TodoTxtMacTests/TTMTask_DueDate_UnitTests.m new file mode 100644 index 0000000..51587f4 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_DueDate_UnitTests.m @@ -0,0 +1,111 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_DueDate_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSDate *dueDate; +@property NSDate *highDate; + +@end + +@implementation TTMTask_DueDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.dueDate = [TTMDateUtility convertStringToDate:@"2020-01-31"]; + self.highDate = [TTMDateUtility convertStringToDate:@"9999-12-31"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_DueDate_WhenAtEndOfTask_ShouldBeDueDate { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.dueDate); +} + +- (void)test_DueDate_WhenInMiddleOfTask_ShouldBeDueDate { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.dueDate); +} + +- (void)test_DueDate_WhenAtStartOfTask_ShouldBeDueDate { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.dueDate); +} + +- (void)test_DueDate_WhenIsEntireTask_ShouldBeDueDate { + NSString *rawText = @"due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.dueDate); +} + +- (void)test_DueDate_WhenMissingLeadingSpace_ShouldBeHighDate { + NSString *rawText = @"pick up groceries-due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.highDate); +} + +- (void)test_DueDate_WhenMissingTrailingSpace_ShouldBeHighDate { + NSString *rawText = @"pick up groceries due:2020-01-31+Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.dueDate, self.highDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_DueState_UnitTests.m b/TodoTxtMacTests/TTMTask_DueState_UnitTests.m new file mode 100644 index 0000000..c72ca42 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_DueState_UnitTests.m @@ -0,0 +1,97 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_DueState_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_DueState_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_DueState_WhenTaskContainsNoDueDate_ShouldBeNotDue { + NSString *rawText = @"(A) test task"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(NotDue, task.dueState); +} + +- (void)test_DueState_WhenTaskContainsFutureDueDate_ShouldBeNotDue { + NSString *rawText = @"(A) pick up groceries due:9999-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(NotDue, task.dueState); +} + +- (void)test_DueState_WhenTaskContainsTodayDueDate_ShouldBeDueToday { + NSString *rawTextPart1 = @"(A) pick up groceries due:"; + NSString *rawTextPart2 = [TTMDateUtility todayAsString]; + NSString *rawText = [rawTextPart1 stringByAppendingString:rawTextPart2]; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(DueToday, task.dueState); +} + +- (void)test_DueState_WhenTaskContainsPastDueDate_ShouldBeOverdue { + NSString *rawText = @"(A) pick up groceries due:2001-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(Overdue, task.dueState); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_IncreasePriority_UnitTests.m b/TodoTxtMacTests/TTMTask_IncreasePriority_UnitTests.m new file mode 100644 index 0000000..ae026a0 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_IncreasePriority_UnitTests.m @@ -0,0 +1,107 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_IncreasePriority_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_IncreasePriority_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_IncreasePriority_WhenPriorityIsC_ShouldSetPriorityToB { + NSString *rawText = @"(C) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task increasePriority]; + NSString *expectedRawText = @"(B) pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenPriorityIsA_ShouldDoNothing { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task increasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenNoPriority_ShouldSetPriorityToA { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task increasePriority]; + NSString *expectedRawText = @"(A) pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenTaskIsComplete_ShouldDoNothing { + NSString *rawText = @"x 2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task increasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +- (void)test_IncreasePriority_WhenTaskIsBlank_ShouldDoNothing { + NSString *rawText = @""; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task increasePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_IncrementDueDate_UnitTests.m b/TodoTxtMacTests/TTMTask_IncrementDueDate_UnitTests.m new file mode 100644 index 0000000..4240416 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_IncrementDueDate_UnitTests.m @@ -0,0 +1,142 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_IncrementDueDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_IncrementDueDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_IncrementDueDate_ByOneDayWhenTaskHasDueDateAtEnd_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByOneDayWhenTaskHasDueDateInMiddle_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByOneDayWhenTaskHasDueDateAtBeginning_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:1]; + NSString *expectedRawText = @"due:2020-02-01 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfTomorrow { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:1]; + NSDate *tomorrow = [TTMDateUtility addDays:1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:tomorrow]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByNegativeOneDayWhenTaskHasDueDateAtEnd_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByNegativeOneDayWhenTaskHasDueDateInMiddle_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} +- (void)test_IncrementDueDate_ByNegativeOneDayWhenTaskHasDueDateAtBeginning_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:-1]; + NSString *expectedRawText = @"due:2020-01-30 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementDueDate_ByNegativeOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfYesterday { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementDueDate:-1]; + NSDate *yesterday = [TTMDateUtility addDays:-1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:yesterday]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_IncrementThresholdDate_UnitTests.m b/TodoTxtMacTests/TTMTask_IncrementThresholdDate_UnitTests.m new file mode 100644 index 0000000..780099a --- /dev/null +++ b/TodoTxtMacTests/TTMTask_IncrementThresholdDate_UnitTests.m @@ -0,0 +1,91 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_IncrementThresholdDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_IncrementThresholdDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_IncrementThresholdDate_WhenTaskHasNoThresholdDate_ShouldIncrementThresholdDateByOneDay { + NSString *rawText = @"pick up groceries t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementThresholdDate:1]; + NSString *expectedRawText = @"pick up groceries t:2020-02-01"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_IncrementThresholdDate_WhenTaskHasNoThresholdDate_ShouldAppendThresholdDateOfTomorrow { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task incrementThresholdDate:1]; + NSDate *tomorrow = [TTMDateUtility addDays:1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" t:", + [TTMDateUtility convertDateToString:tomorrow]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_Init_UnitTests.m b/TodoTxtMacTests/TTMTask_Init_UnitTests.m new file mode 100644 index 0000000..628d7f4 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_Init_UnitTests.m @@ -0,0 +1,115 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_Init_UnitTests : XCTestCase + +@property NSString *rawText; +@property NSUInteger taskId; +@property NSDate *prependedDate; + +@end + +@implementation TTMTask_Init_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.rawText = @"pick up groceries"; + self.taskId = 10; + self.prependedDate = [TTMDateUtility today]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_init_WhenGivenRawTextAndTaskId_RawTextShouldEqualRawText { + TTMTask *task = [[TTMTask alloc] initWithRawText:self.rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(self.rawText, task.rawText); +} + +- (void)test_init_WhenGivenBlankRawTextAndTaskId_RawTextShouldBeBlank { + TTMTask *task = [[TTMTask alloc] initWithRawText:@"" withTaskId:self.taskId]; + XCTAssertEqualObjects(@"", task.rawText); +} + +- (void)test_init_WhenGivenRawTextAndTaskId_IdShouldEqualId { + TTMTask *task = [[TTMTask alloc] initWithRawText:self.rawText withTaskId:self.taskId]; + XCTAssertEqual(self.taskId, task.taskId); +} + +- (void)test_init_WhenGivenRawTextAndTaskIdAndPrependedDate_RawTextShouldEqualRawTextWithPrependedDate { + TTMTask *task = [[TTMTask alloc] initWithRawText:self.rawText + withTaskId:self.taskId + withPrependedDate:self.prependedDate]; + NSString *rawText = [NSString stringWithFormat:@"%@%c%@", + [TTMDateUtility convertDateToString:self.prependedDate], + ' ', + self.rawText]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +- (void)test_init_WhenGivenRawTextAndTaskIdAndPrependedDate_IdShouldEqualId { + TTMTask *task = [[TTMTask alloc] initWithRawText:self.rawText + withTaskId:self.taskId + withPrependedDate:self.prependedDate]; + XCTAssertEqual(self.taskId, task.taskId); +} + +- (void)test_init_WhenGivenRawTextAndTaskIdAndPrependedDate_CreationDateShouldEqualPrependedDate { + TTMTask *task = [[TTMTask alloc] initWithRawText:self.rawText + withTaskId:self.taskId + withPrependedDate:self.prependedDate]; + XCTAssertEqualObjects(self.prependedDate, task.creationDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_IsCompleted_UnitTests.m b/TodoTxtMacTests/TTMTask_IsCompleted_UnitTests.m new file mode 100644 index 0000000..8c4eb2a --- /dev/null +++ b/TodoTxtMacTests/TTMTask_IsCompleted_UnitTests.m @@ -0,0 +1,126 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_IsCompleted_UnitTests : XCTestCase + +@property NSString *rawText; +@property NSUInteger taskId; + +@end + +@implementation TTMTask_IsCompleted_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.rawText = @"pick up groceries"; + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_IsCompleted_WhenCompleted_ShouldBeTrue { + NSString *rawText = @"x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertTrue(task.isCompleted); +} + +- (void)test_IsCompleted_WhenNotCompleted_ShouldBeFalse { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedFormatHasCapitalX_ShouldBeFalse { + NSString *rawText = @"X 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedFormatHasNoDate_ShouldBeFalse { + NSString *rawText = @"x pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedDateHasNoLeadingSpace_ShouldBeFalse { + NSString *rawText = @"x2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedDateHasNoTrailingSpace_ShouldBeFalse { + NSString *rawText = @"x 2020-01-31pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedDateHasTwoLeadingSpaces_ShouldBeFalse { + NSString *rawText = @"x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedFormatHasInvalidDate_ShouldBeFalse { + NSString *rawText = @"x 2020-13-32 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_IsCompleted_WhenCompletedFormatHasLeadingSpace_ShouldBeFalse { + NSString *rawText = @" x 2020-01-31 pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertFalse(task.isCompleted); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_MarkComplete_UnitTests.m b/TodoTxtMacTests/TTMTask_MarkComplete_UnitTests.m new file mode 100644 index 0000000..172fd9c --- /dev/null +++ b/TodoTxtMacTests/TTMTask_MarkComplete_UnitTests.m @@ -0,0 +1,92 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_MarkComplete_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_MarkComplete_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_MarkComplete_WhenTaskIsNotComplete_ShouldMarkComplete { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task markComplete]; + XCTAssertTrue(task.isCompleted); +} + +- (void)test_MarkComplete_WhenTaskIsNotComplete_ShouldSetCompletionDateToToday { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task markComplete]; + XCTAssertEqualObjects([TTMDateUtility today], task.completionDate); +} + +- (void)test_MarkComplete_WhenTaskIsComplete_ShouldDoNothing { + NSString *rawText = @"x 2020-12-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task markComplete]; + XCTAssertTrue(task.isCompleted); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_MarkIncomplete_UnitTests.m b/TodoTxtMacTests/TTMTask_MarkIncomplete_UnitTests.m new file mode 100644 index 0000000..c50a103 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_MarkIncomplete_UnitTests.m @@ -0,0 +1,84 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_MarkIncomplete_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_MarkIncomplete_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_MarkComplete_WhenTaskIsIncomplete_ShouldDoNothing { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task markIncomplete]; + XCTAssertFalse(task.isCompleted); +} + +- (void)test_MarkComplete_WhenTaskIsComplete_ShouldMarkIncomplete { + NSString *rawText = @"x 2020-12-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task markIncomplete]; + XCTAssertFalse(task.isCompleted); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_Postpone_UnitTests.m b/TodoTxtMacTests/TTMTask_Postpone_UnitTests.m new file mode 100644 index 0000000..4b40201 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_Postpone_UnitTests.m @@ -0,0 +1,141 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_Postpone_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_Postpone_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_Postpone_ByOneDayWhenTaskHasDueDateAtEnd_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_Postpone_ByOneDayWhenTaskHasDueDateInMiddle_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:1]; + NSString *expectedRawText = @"pick up groceries due:2020-02-01 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} +- (void)test_Postpone_ByOneDayWhenTaskHasDueDateAtBeginning_ShouldIncrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:1]; + NSString *expectedRawText = @"due:2020-02-01 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_Postpone_ByOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfTomorrow { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:1]; + NSDate *tomorrow = [TTMDateUtility addDays:1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:tomorrow]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_Postpone_ByNegativeOneDayWhenTaskHasDueDateAtEnd_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_Postpone_ByNegativeOneDayWhenTaskHasDueDateInMiddle_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"pick up groceries due:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:-1]; + NSString *expectedRawText = @"pick up groceries due:2020-01-30 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} +- (void)test_Postpone_ByNegativeOneDayWhenTaskHasDueDateAtBeginning_ShouldDecrementDueDateByOneDay { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:-1]; + NSString *expectedRawText = @"due:2020-01-30 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_Postpone_ByNegativeOneDayWhenTaskHasNoDueDate_ShouldAppendDueDateOfYesterday { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task postponeTask:-1]; + NSDate *yesterday = [TTMDateUtility addDays:-1 toDate:[TTMDateUtility today]]; + NSString *expectedRawText = [NSString stringWithFormat:@"%@%@%@", + rawText, + @" due:", + [TTMDateUtility convertDateToString:yesterday]]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_PrependText_UnitTests.m b/TodoTxtMacTests/TTMTask_PrependText_UnitTests.m new file mode 100644 index 0000000..f045267 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_PrependText_UnitTests.m @@ -0,0 +1,119 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_PrependText_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSString *textToPrepend; + +@end + +@implementation TTMTask_PrependText_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.textToPrepend = @"[text to prepend]"; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_PrependText_WhenCompleteWithCreationDate_ShouldPrependAfterCreationDate { + NSString *rawText = @"x 2020-01-31 2020-01-01 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + NSString *expectedRawText = @"x 2020-01-31 2020-01-01 [text to prepend] pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_PrependText_WhenCompleteWithNoCreationDate_ShouldPrependAfterCompletionDate { + NSString *rawText = @"x 2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + NSString *expectedRawText = @"x 2020-01-31 [text to prepend] pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_PrependText_WhenIncompleteWithNoCreationDate_ShouldPrependAtBeginning { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + NSString *expectedRawText = @"[text to prepend] pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_PrependText_WhenIncompleteWithPriorityAndNoCreationDate_ShouldPrependAfterPriority { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + NSString *expectedRawText = @"(A) [text to prepend] pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_PrependText_WhenIncompleteWithPriorityAndCreationDate_ShouldPrependAfterCreationDate { + NSString *rawText = @"(A) 2020-01-01 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + NSString *expectedRawText = @"(A) 2020-01-01 [text to prepend] pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_PrependText_WhenTaskIsBlank_ShouldPrependAtBeginning { + NSString *rawText = @""; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task prependText:self.textToPrepend]; + XCTAssertEqualObjects(self.textToPrepend, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_Priority_UnitTests.m b/TodoTxtMacTests/TTMTask_Priority_UnitTests.m new file mode 100644 index 0000000..a642c7a --- /dev/null +++ b/TodoTxtMacTests/TTMTask_Priority_UnitTests.m @@ -0,0 +1,112 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_Priority_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_Priority_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_Priority_WhenPriorityIsUppercaseA_ShouldBeA { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('A', task.priority); +} + +- (void)test_Priority_WhenPriorityIsLowercaseA_ShouldBeTilde { + NSString *rawText = @"(a) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +- (void)test_Priority_WhenPriorityIsNotAnUppercaseLetter_ShouldBeTilde { + NSString *rawText = @"(1) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +- (void)test_Priority_WhenPriorityIsNotAtBeginningOfRawText_ShouldBeTilde { + NSString *rawText = @" (A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +- (void)test_Priority_WhenPriorityHasNoSpaceAfter_ShouldBeTilde { + NSString *rawText = @"(A)pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +- (void)test_Priority_WhenNoPriority_ShouldBeTilde { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +- (void)test_Priority_WhenRawTextIsBlank_ShouldBeTilde { + NSString *rawText = @""; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual('~', task.priority); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_Projects_UnitTests.m b/TodoTxtMacTests/TTMTask_Projects_UnitTests.m new file mode 100644 index 0000000..cb41646 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_Projects_UnitTests.m @@ -0,0 +1,94 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_Projects_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_Projects_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_Projects_WhenTaskHasOneProject_ShouldBeOneProject { + NSString *rawText = @"pick up groceries +Chores"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"+Chores", task.projects); +} + +- (void)test_Projects_WhenTaskHasMultipleProjects_ShouldBeAllProjectsAlphabetized { + NSString *rawText = @"pick up groceries +Shopping +Chores +Errands"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"+Chores, +Errands, +Shopping", task.projects); +} + +- (void)test_Projects_WhenTaskHasMultipleProjectsWithOddPunctuation_ShouldBeAllProjectsAlphabetized { + NSString *rawText = @"pick up groceries +Shopping; +Chores+Personal +-Errands-"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"+-Errands-, +Chores+Personal, +Shopping;", task.projects); +} + +- (void)test_Projects_WhenTaskHasNoProjects_ShouldBeEmptyString { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(@"", task.projects); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_RemoveDueDate_UnitTests.m b/TodoTxtMacTests/TTMTask_RemoveDueDate_UnitTests.m new file mode 100644 index 0000000..da15207 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_RemoveDueDate_UnitTests.m @@ -0,0 +1,119 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_RemoveDueDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_RemoveDueDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_RemoveDueDate_WhenTaskHasDueDateAtEnd_ShouldRemoveDueDate { + NSString *rawText = @"pick up groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveDueDate_WhenTaskHasDueDateAtBeginning_ShouldRemoveDueDate { + NSString *rawText = @"due:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveDueDate_WhenTaskHasDueDateInMiddle_ShouldRemoveDueDate { + NSString *rawText = @"pick up due:2020-01-31 groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveDueDate__WhenTaskIsOnlyTheDueDate_ShouldRemoveDueDate { + NSString *rawText = @"due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @""; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveDueDate_WhenTaskHasMultipleDueDates_ShouldRemoveAllDueDates { + NSString *rawText = @"due:2020-01-31 pick up due:2020-01-31 groceries due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveDueDate_WhenTaskIsOnlyDueDate_ShouldRemoveDueDate { + NSString *rawText = @"due:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeDueDate]; + NSString *expectedRawText = @""; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_RemovePriority_UnitTests.m b/TodoTxtMacTests/TTMTask_RemovePriority_UnitTests.m new file mode 100644 index 0000000..d1567a2 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_RemovePriority_UnitTests.m @@ -0,0 +1,85 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_RemovePriority_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_RemovePriority_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_RemovePriority_WhenTaskHasPriority_ShouldRemovePriority { + NSString *rawText = @"(C) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removePriority]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)testRemovePriority_WhenTaskHasNoPriority_ShouldDoNothing { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removePriority]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_RemoveThresholdDate_UnitTests.m b/TodoTxtMacTests/TTMTask_RemoveThresholdDate_UnitTests.m new file mode 100644 index 0000000..123a19b --- /dev/null +++ b/TodoTxtMacTests/TTMTask_RemoveThresholdDate_UnitTests.m @@ -0,0 +1,119 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_RemoveThresholdDate_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_RemoveThresholdDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_RemoveThresholdDate_WhenTaskHasThresholdDateAtEnd_ShouldRemoveThresholdDate { + NSString *rawText = @"pick up groceries t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveThresholdDate_WhenTaskHasThresholdDateAtBeginning_ShouldRemoveThresholdDate { + NSString *rawText = @"t:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveThresholdDate_WhenTaskHasThresholdDateInMiddle_ShouldRemoveThresholdDate { + NSString *rawText = @"pick up t:2020-01-31 groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveThresholdDate__WhenTaskIsOnlyTheThresholdDate_ShouldRemoveThresholdDate { + NSString *rawText = @"t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @""; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveThresholdDate_WhenTaskHasMultipleThresholdDates_ShouldRemoveAllThresholdDates { + NSString *rawText = @"t:2020-01-31 pick up t:2020-01-31 groceries t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @"pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_RemoveThresholdDate_WhenTaskIsOnlyThresholdDate_ShouldRemoveThresholdDate { + NSString *rawText = @"t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task removeThresholdDate]; + NSString *expectedRawText = @""; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_ReplaceText_UnitTests.m b/TodoTxtMacTests/TTMTask_ReplaceText_UnitTests.m new file mode 100644 index 0000000..bd36920 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_ReplaceText_UnitTests.m @@ -0,0 +1,84 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "TTMTask.h" + +@interface TTMTask_ReplaceText_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_ReplaceText_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_ReplaceText_WhenSearchTextIsFound_ShouldReplaceSearchText { + NSString *rawText = @"pick up groceries @Errands"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + NSString *expectedRawText = @"pick up car @Errands"; + [task replaceText:@"groceries" withText:@"car"]; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_ReplaceText_WhenSearchTextIsNotFound_ShouldDoNothing { + NSString *rawText = @"pick up groceries @Errands"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task replaceText:@"bananas" withText:@"car"]; + XCTAssertEqualObjects(rawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_SetDueDate_UnitTests.m b/TodoTxtMacTests/TTMTask_SetDueDate_UnitTests.m new file mode 100644 index 0000000..12df5ae --- /dev/null +++ b/TodoTxtMacTests/TTMTask_SetDueDate_UnitTests.m @@ -0,0 +1,121 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_SetDueDate_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSDate *dueDate; + +@end + +@implementation TTMTask_SetDueDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.dueDate = [TTMDateUtility convertStringToDate:@"2020-01-31"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testSetDueDate { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"pick up groceries due:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetDueDate_WhenTaskHasNoDueDate_ShouldAppendDueDate { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"pick up groceries due:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetDueDate_WhenTaskHasDueDateAtEnd_ShouldReplaceDueDate { + NSString *rawText = @"pick up groceries due:2020-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"pick up groceries due:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetDueDate_WhenTaskHasDueDateInMiddle_ShouldReplaceDueDate { + NSString *rawText = @"pick up groceries due:2020-01-01 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"pick up groceries due:2020-01-31 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetDueDate_WhenTaskHasDueDateAtBeginning_ShouldReplaceDueDate { + NSString *rawText = @"due:2020-01-01 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"due:2020-01-31 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetDueDate_WhenTaskHasMultipleDueDates_ShouldReplaceAllDueDates { + NSString *rawText = @"pick up groceries due:2015-12-15 due:2015-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setDueDate:self.dueDate]; + NSString *expectedRawText = @"pick up groceries due:2020-01-31 due:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_SetThresholdDate_UnitTests.m b/TodoTxtMacTests/TTMTask_SetThresholdDate_UnitTests.m new file mode 100644 index 0000000..c9ccdbe --- /dev/null +++ b/TodoTxtMacTests/TTMTask_SetThresholdDate_UnitTests.m @@ -0,0 +1,113 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_SetThresholdDate_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSDate *thresholdDate; + +@end + +@implementation TTMTask_SetThresholdDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.thresholdDate = [TTMDateUtility convertStringToDate:@"2020-01-31"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_SetThresholdDate_WhenTaskHasNoThresholdDate_ShouldAppendThresholdDate { + NSString *rawText = @"pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setThresholdDate:self.thresholdDate]; + NSString *expectedRawText = @"pick up groceries t:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetThresholdDate_WhenTaskHasThresholdDateAtEnd_ShouldReplaceThresholdDate { + NSString *rawText = @"pick up groceries t:2020-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setThresholdDate:self.thresholdDate]; + NSString *expectedRawText = @"pick up groceries t:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetThresholdDate_WhenTaskHasThresholdDateInMiddle_ShouldReplaceThresholdDate { + NSString *rawText = @"pick up groceries t:2020-01-01 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setThresholdDate:self.thresholdDate]; + NSString *expectedRawText = @"pick up groceries t:2020-01-31 +Personal"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetThresholdDate_WhenTaskHasThresholdDateAtBeginning_ShouldReplaceThresholdDate { + NSString *rawText = @"t:2020-01-01 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setThresholdDate:self.thresholdDate]; + NSString *expectedRawText = @"t:2020-01-31 pick up groceries"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +- (void)test_SetThresholdDate_WhenTaskHasMultipleThresholdDates_ShouldReplaceAllThresholdDates { + NSString *rawText = @"pick up groceries t:2015-12-15 t:2015-12-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task setThresholdDate:self.thresholdDate]; + NSString *expectedRawText = @"pick up groceries t:2020-01-31 t:2020-01-31"; + XCTAssertEqualObjects(expectedRawText, task.rawText); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_ThresholdDate_UnitTests.m b/TodoTxtMacTests/TTMTask_ThresholdDate_UnitTests.m new file mode 100644 index 0000000..28ea425 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_ThresholdDate_UnitTests.m @@ -0,0 +1,111 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_ThresholdDate_UnitTests : XCTestCase + +@property NSUInteger taskId; +@property NSDate *thresholdDate; +@property NSDate *lowDate; + +@end + +@implementation TTMTask_ThresholdDate_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; + self.thresholdDate = [TTMDateUtility convertStringToDate:@"2020-01-31"]; + self.lowDate = [TTMDateUtility convertStringToDate:@"1900-01-01"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_ThresholdDate_WhenAtEndOfTask_ShouldBeThresholdDate { + NSString *rawText = @"pick up groceries t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.thresholdDate); +} + +- (void)test_ThresholdDate_WhenInMiddleOfTask_ShouldBeThresholdDate { + NSString *rawText = @"pick up groceries t:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.thresholdDate); +} + +- (void)test_ThresholdDate_WhenAtStartOfTask_ShouldBeThresholdDate { + NSString *rawText = @"t:2020-01-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.thresholdDate); +} + +- (void)test_ThresholdDate_WhenIsEntireTask_ShouldBeThresholdDate { + NSString *rawText = @"t:2020-01-31"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.thresholdDate); +} + +- (void)test_ThresholdDate_WhenMissingLeadingSpace_ShouldBeLowDate { + NSString *rawText = @"pick up groceries-t:2020-01-31 +Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.lowDate); +} + +- (void)test_ThresholdDate_WhenMissingTrailingSpace_ShouldBeLowDate { + NSString *rawText = @"pick up groceries t:2020-01-31+Personal"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqualObjects(task.thresholdDate, self.lowDate); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_ThresholdState_UnitTests.m b/TodoTxtMacTests/TTMTask_ThresholdState_UnitTests.m new file mode 100644 index 0000000..56be322 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_ThresholdState_UnitTests.m @@ -0,0 +1,120 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" +#import "TTMDateUtility.h" + +@interface TTMTask_ThresholdState_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_ThresholdState_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testThresholdStateBefore { + NSString *rawText = @"(A) pick up groceries t:2020-01-31 due:2020-01-31"; + NSUInteger taskId = 0; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; + XCTAssertEqual(task.thresholdState, BeforeThresholdDate); +} + +- (void)testThresholdStateOn { + NSString *rawTextPart1 = @"(A) pick up groceries t:"; + NSString *rawTextPart2 = [TTMDateUtility todayAsString]; + NSString *rawText = [rawTextPart1 stringByAppendingString:rawTextPart2]; + NSUInteger taskId = 0; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; + XCTAssertEqual(task.thresholdState, OnThresholdDate); +} + +- (void)testThresholdStateAfter { + NSString *rawText = @"(A) pick up groceries t:2001-01-01 due:2020-01-31"; + NSUInteger taskId = 0; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; + XCTAssertEqual(task.thresholdState, AfterThresholdDate); +} + +- (void)test_ThresholdState_WhenTaskContainsNoThresholdDate_ShouldBeAfterThresholdDate { + NSString *rawText = @"(A) test task"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(AfterThresholdDate, task.thresholdState); +} + +- (void)test_ThresholdState_WhenTaskContainsFutureThresholdDate_ShouldBeBeforeThreshold { + NSString *rawText = @"(A) pick up groceries t:9999-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(BeforeThresholdDate, task.thresholdState); +} + +- (void)test_ThresholdState_WhenTaskContainsTodayThresholdDate_ShouldBeOnThresholdDate { + NSString *rawTextPart1 = @"(A) pick up groceries t:"; + NSString *rawTextPart2 = [TTMDateUtility todayAsString]; + NSString *rawText = [rawTextPart1 stringByAppendingString:rawTextPart2]; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(OnThresholdDate, task.thresholdState); +} + +- (void)test_ThresholdState_WhenTaskContainsPastThresholdDate_ShouldBeAfterThresholdDate { + NSString *rawText = @"(A) pick up groceries t:2001-01-01"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + XCTAssertEqual(AfterThresholdDate, task.thresholdState); +} + +@end diff --git a/TodoTxtMacTests/TTMTask_ToggleCompletion_UnitTests.m b/TodoTxtMacTests/TTMTask_ToggleCompletion_UnitTests.m new file mode 100644 index 0000000..0237648 --- /dev/null +++ b/TodoTxtMacTests/TTMTask_ToggleCompletion_UnitTests.m @@ -0,0 +1,84 @@ +/** + * @author Michael Descy + * @copyright 2014-2015 Michael Descy + * @discussion Dual-licensed under the GNU General Public License and the MIT License + * + * + * + * @license GNU General Public License http://www.gnu.org/licenses/gpl.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * + * + * @license The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "TTMTask.h" + +@interface TTMTask_ToggleCompletionStatus_UnitTests : XCTestCase + +@property NSUInteger taskId; + +@end + +@implementation TTMTask_ToggleCompletionStatus_UnitTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + self.taskId = 10; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)test_ToggleCompletionStatus_WhenTaskIsNotComplete_ShouldMarkComplete { + NSString *rawText = @"(A) pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task toggleCompletionStatus]; + XCTAssertTrue(task.isCompleted); +} + +- (void)test_ToggleCompletionStatus_WhenTaskIsComplete_ShouldMarkIncomplete { + NSString *rawText = @"x 2020-12-31 pick up groceries"; + TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:self.taskId]; + [task toggleCompletionStatus]; + XCTAssertFalse(task.isCompleted); +} + +@end diff --git a/TodoTxtMacTests/TTMTasklistMetadataTests.m b/TodoTxtMacTests/TTMTasklistMetadata_UnitTests.m similarity index 100% rename from TodoTxtMacTests/TTMTasklistMetadataTests.m rename to TodoTxtMacTests/TTMTasklistMetadata_UnitTests.m diff --git a/TodoTxtMacTests/TodoTxtMacTests.m b/TodoTxtMacTests/TodoTxtMacTests.m deleted file mode 100644 index fe825f9..0000000 --- a/TodoTxtMacTests/TodoTxtMacTests.m +++ /dev/null @@ -1,392 +0,0 @@ -/** - * @author Michael Descy - * @copyright 2014-2015 Michael Descy - * @discussion Dual-licensed under the GNU General Public License and the MIT License - * - * - * - * @license GNU General Public License http://www.gnu.org/licenses/gpl.html - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - * - * - * @license The MIT License (MIT) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#import -#import "TTMTask.h" -#import "TTMDateUtility.h" - -@interface TodoTxtMacTests : XCTestCase - -@end - -@implementation TodoTxtMacTests - -- (void)setUp { - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testRawTextOfNormalTask { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.rawText, rawText); -} - -- (void)testInitWithRawTextwithTaskIdwithPrependedDate { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:@"yyyy-MM-dd"]; - NSDate *date = [dateFormatter dateFromString:@"2020-01-01"]; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId withPrependedDate:date]; - XCTAssertEqualObjects(task.rawText, @"2020-01-01 pick up groceries"); -} - -- (void)testIsCompleted { - NSString *rawText = @"x 2020-01-31 pick up groceries due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertTrue(task.isCompleted); -} - -- (void)testDueDate { - NSString *rawText = @"pick up groceries due:2020-01-31"; - NSUInteger taskId = 0; - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-31"]; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.dueDate, date); -} - -- (void)testSetDueDate { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-31"]; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - [task setDueDate:date]; - XCTAssertEqualObjects(task.dueDate, date); -} - -- (void)testRemoveDueDate { - NSString *rawText = @"pick up groceries t:2020-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *modifiedText = @"pick up groceries t:2020-01-01"; - [task removeDueDate]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testDueDateText { - NSString *rawText = @"pick up groceries due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.dueDateText, @"2020-01-31"); -} - -- (void)testCreationDate { - NSString *rawText = @"2020-01-01 pick up groceries"; - NSUInteger taskId = 0; - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"]; - NSDate *date = [dateFormatter dateFromString:@"2020-01-01 00:00:00 GMT"]; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId withPrependedDate:date]; - NSLog(@"creationDate: %@", task.creationDate); - NSLog(@"date: %@", date); - XCTAssertEqualObjects(task.creationDate, date); -} - -- (void)testThresholdDate { - NSString *rawText = @"pick up groceries t:2020-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-01"]; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.thresholdDate, date); -} - -- (void)testDateConversions { - NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; - NSLog(@"firstDate: %@", firstDate); - NSString *firstDateString = [TTMDateUtility convertDateToString:firstDate]; - NSLog(@"firstDateString: %@", firstDateString); - NSDate *secondDate = [TTMDateUtility convertStringToDate:firstDateString]; - NSLog(@"secondDate: %@", secondDate); - XCTAssertEqualObjects(firstDate, secondDate); -} - -- (void)testAddDaysToDate { - NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; - NSDate *secondDate = [TTMDateUtility convertStringToDate:@"2014-01-02"]; - NSDate *firstDateModified = [TTMDateUtility addDays:1 toDate:firstDate]; - NSLog(@"new date: %@", firstDateModified); - XCTAssertEqualObjects(firstDateModified, secondDate); -} - -- (void)testAddNegativeDaysToDate { - NSDate *firstDate = [TTMDateUtility convertStringToDate:@"2014-01-02"]; - NSDate *secondDate = [TTMDateUtility convertStringToDate:@"2014-01-01"]; - NSDate *firstDateModified = [TTMDateUtility addDays:-1 toDate:firstDate]; - NSLog(@"new date: %@", firstDateModified); - XCTAssertEqualObjects(firstDateModified, secondDate); -} - -- (void)testPostponeTaskWithDueDate { - NSString *rawText = @"pick up groceries due:2020-01-01"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSLog(@"due date before change: %@", task.dueDate); - [task postponeTask:1]; - NSLog(@"due date after change: %@", task.dueDate); - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-02"]; - XCTAssertEqualObjects(task.dueDate, date); -} - -- (void)testPostponeTaskNegativeWithDueDate { - NSString *rawText = @"pick up groceries due:2020-01-02"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - [task postponeTask:-1]; - XCTAssertEqualObjects(task.dueDate, [TTMDateUtility convertStringToDate:@"2020-01-01"]); -} - -- (void)testChangingRawTextToBlankString { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - task.rawText = @""; - XCTAssertEqualObjects(task.rawText, @""); -} - -- (void)testProjects { - NSString *rawText = @"pick up groceries +Chores +Shopping +Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.projects, @"+Chores, +Errands, +Shopping"); -} - -- (void)testContexts { - NSString *rawText = @"pick up groceries @Chores @Shopping @Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.contexts, @"@Chores, @Errands, @Shopping"); -} - -- (void)testPriority { - NSString *rawText = @"(A) pick up groceries @Chores @Shopping @Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqualObjects(task.priorityText, @"A"); -} - -- (void)testIncreasePriority { - NSString *rawText = @"(C) pick up groceries @Chores @Shopping @Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - [task increasePriority]; - XCTAssertEqualObjects(task.priorityText, @"B"); -} - -- (void)testDecreasePriority { - NSString *rawText = @"(A) pick up groceries @Chores @Shopping @Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - [task decreasePriority]; - XCTAssertEqualObjects(task.priorityText, @"B"); -} - -- (void)testRemovePriority { - NSString *rawText = @"(A) pick up groceries @Chores @Shopping @Errands"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - [task removePriority]; - XCTAssertEqualObjects(task.rawText, @"pick up groceries @Chores @Shopping @Errands"); -} - -- (void)testDueStateOverdue { - NSString *rawText = @"(A) pick up groceries due:2001-01-01"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.dueState, Overdue); -} - -- (void)testDueStateDueToday { - NSString *rawTextPart1 = @"(A) pick up groceries due:"; - NSString *rawTextPart2 = [TTMDateUtility todayAsString]; - NSString *rawText = [rawTextPart1 stringByAppendingString:rawTextPart2]; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.dueState, DueToday); -} - -- (void)testDueStateNotdue { - NSString *rawText = @"(A) pick up groceries due:2020-12-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.dueState, NotDue); -} - -- (void)testThresholdStateBefore { - NSString *rawText = @"(A) pick up groceries t:2020-01-31 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.thresholdState, BeforeThresholdDate); -} - -- (void)testThresholdStateOn { - NSString *rawTextPart1 = @"(A) pick up groceries t:"; - NSString *rawTextPart2 = [TTMDateUtility todayAsString]; - NSString *rawText = [rawTextPart1 stringByAppendingString:rawTextPart2]; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.thresholdState, OnThresholdDate); -} - -- (void)testThresholdStateAfter { - NSString *rawText = @"(A) pick up groceries t:2001-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - XCTAssertEqual(task.thresholdState, AfterThresholdDate); -} - -- (void)testSetThresholdDate { - NSString *rawText = @"pick up groceries due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-01"]; - [task setThresholdDate:date]; - XCTAssertEqualObjects(task.thresholdDate, date); -} - -- (void)testIncrementThresholdDate { - NSString *rawText = @"(A) pick up groceries t:2020-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSDate *date = [TTMDateUtility convertStringToDate:@"2020-01-02"]; - [task incrementThresholdDay:1]; - XCTAssertEqualObjects(task.thresholdDate, date); -} - -- (void)testIncrementThresholdDateWhenNoThresholdDate { - NSString *rawText = @"(A) pick up groceries due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSDate *date = [TTMDateUtility addDays:1 toDate:[TTMDateUtility today]]; - [task incrementThresholdDay:1]; - XCTAssertEqualObjects(task.thresholdDate, date); -} - -- (void)testDecrementThresholdDate { - NSString *rawText = @"(A) pick up groceries t:2020-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSDate *date = [TTMDateUtility convertStringToDate:@"2019-12-31"]; - [task decrementThresholdDay:1]; - XCTAssertEqualObjects(task.thresholdDate, date); -} - -- (void)testRemoveThresholdDate { - NSString *rawText = @"pick up groceries t:2020-01-01 due:2020-01-31"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *modifiedText = @"pick up groceries due:2020-01-31"; - [task removeThresholdDate]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testAppendText { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *textToAppend = @"due:2020-01-31"; - NSString *modifiedText = @"pick up groceries due:2020-01-31"; - [task appendText:textToAppend]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testPrependText { - NSString *rawText = @"pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *textToPrepend = @"t:2020-01-01"; - NSString *modifiedText = @"t:2020-01-01 pick up groceries"; - [task prependText:textToPrepend]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testPrependTextWithPriority { - NSString *rawText = @"(C) pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *textToPrepend = @"t:2020-01-01"; - NSString *modifiedText = @"(C) t:2020-01-01 pick up groceries"; - [task prependText:textToPrepend]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testPrependTextWithPriorityAndCreationDate { - NSString *rawText = @"(C) 2014-01-01 pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *textToPrepend = @"t:2020-01-01"; - NSString *modifiedText = @"(C) 2014-01-01 t:2020-01-01 pick up groceries"; - [task prependText:textToPrepend]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testPrependTextCreationDate { - NSString *rawText = @"2014-01-01 pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *textToPrepend = @"t:2020-01-01"; - NSString *modifiedText = @"2014-01-01 t:2020-01-01 pick up groceries"; - [task prependText:textToPrepend]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -- (void)testReplaceText { - NSString *rawText = @"(C) 2014-01-01 pick up groceries"; - NSUInteger taskId = 0; - TTMTask *task = [[TTMTask alloc] initWithRawText:rawText withTaskId:taskId]; - NSString *modifiedText = @"(C) 2014-01-01 pick up car"; - [task replaceText:@"groceries" withText:@"car"]; - XCTAssertEqualObjects(task.rawText, modifiedText); -} - -@end