1package assertions 2 3import ( 4 "fmt" 5 "reflect" 6 "strings" 7) 8 9// ShouldStartWith receives exactly 2 string parameters and ensures that the first starts with the second. 10func ShouldStartWith(actual interface{}, expected ...interface{}) string { 11 if fail := need(1, expected); fail != success { 12 return fail 13 } 14 15 value, valueIsString := actual.(string) 16 prefix, prefixIsString := expected[0].(string) 17 18 if !valueIsString || !prefixIsString { 19 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 20 } 21 22 return shouldStartWith(value, prefix) 23} 24func shouldStartWith(value, prefix string) string { 25 if !strings.HasPrefix(value, prefix) { 26 shortval := value 27 if len(shortval) > len(prefix) { 28 shortval = shortval[:len(prefix)] + "..." 29 } 30 return serializer.serialize(prefix, shortval, fmt.Sprintf(shouldHaveStartedWith, value, prefix)) 31 } 32 return success 33} 34 35// ShouldNotStartWith receives exactly 2 string parameters and ensures that the first does not start with the second. 36func ShouldNotStartWith(actual interface{}, expected ...interface{}) string { 37 if fail := need(1, expected); fail != success { 38 return fail 39 } 40 41 value, valueIsString := actual.(string) 42 prefix, prefixIsString := expected[0].(string) 43 44 if !valueIsString || !prefixIsString { 45 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 46 } 47 48 return shouldNotStartWith(value, prefix) 49} 50func shouldNotStartWith(value, prefix string) string { 51 if strings.HasPrefix(value, prefix) { 52 if value == "" { 53 value = "<empty>" 54 } 55 if prefix == "" { 56 prefix = "<empty>" 57 } 58 return fmt.Sprintf(shouldNotHaveStartedWith, value, prefix) 59 } 60 return success 61} 62 63// ShouldEndWith receives exactly 2 string parameters and ensures that the first ends with the second. 64func ShouldEndWith(actual interface{}, expected ...interface{}) string { 65 if fail := need(1, expected); fail != success { 66 return fail 67 } 68 69 value, valueIsString := actual.(string) 70 suffix, suffixIsString := expected[0].(string) 71 72 if !valueIsString || !suffixIsString { 73 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 74 } 75 76 return shouldEndWith(value, suffix) 77} 78func shouldEndWith(value, suffix string) string { 79 if !strings.HasSuffix(value, suffix) { 80 shortval := value 81 if len(shortval) > len(suffix) { 82 shortval = "..." + shortval[len(shortval)-len(suffix):] 83 } 84 return serializer.serialize(suffix, shortval, fmt.Sprintf(shouldHaveEndedWith, value, suffix)) 85 } 86 return success 87} 88 89// ShouldEndWith receives exactly 2 string parameters and ensures that the first does not end with the second. 90func ShouldNotEndWith(actual interface{}, expected ...interface{}) string { 91 if fail := need(1, expected); fail != success { 92 return fail 93 } 94 95 value, valueIsString := actual.(string) 96 suffix, suffixIsString := expected[0].(string) 97 98 if !valueIsString || !suffixIsString { 99 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 100 } 101 102 return shouldNotEndWith(value, suffix) 103} 104func shouldNotEndWith(value, suffix string) string { 105 if strings.HasSuffix(value, suffix) { 106 if value == "" { 107 value = "<empty>" 108 } 109 if suffix == "" { 110 suffix = "<empty>" 111 } 112 return fmt.Sprintf(shouldNotHaveEndedWith, value, suffix) 113 } 114 return success 115} 116 117// ShouldContainSubstring receives exactly 2 string parameters and ensures that the first contains the second as a substring. 118func ShouldContainSubstring(actual interface{}, expected ...interface{}) string { 119 if fail := need(1, expected); fail != success { 120 return fail 121 } 122 123 long, longOk := actual.(string) 124 short, shortOk := expected[0].(string) 125 126 if !longOk || !shortOk { 127 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 128 } 129 130 if !strings.Contains(long, short) { 131 return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveContainedSubstring, long, short)) 132 } 133 return success 134} 135 136// ShouldNotContainSubstring receives exactly 2 string parameters and ensures that the first does NOT contain the second as a substring. 137func ShouldNotContainSubstring(actual interface{}, expected ...interface{}) string { 138 if fail := need(1, expected); fail != success { 139 return fail 140 } 141 142 long, longOk := actual.(string) 143 short, shortOk := expected[0].(string) 144 145 if !longOk || !shortOk { 146 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 147 } 148 149 if strings.Contains(long, short) { 150 return fmt.Sprintf(shouldNotHaveContainedSubstring, long, short) 151 } 152 return success 153} 154 155// ShouldBeBlank receives exactly 1 string parameter and ensures that it is equal to "". 156func ShouldBeBlank(actual interface{}, expected ...interface{}) string { 157 if fail := need(0, expected); fail != success { 158 return fail 159 } 160 value, ok := actual.(string) 161 if !ok { 162 return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) 163 } 164 if value != "" { 165 return serializer.serialize("", value, fmt.Sprintf(shouldHaveBeenBlank, value)) 166 } 167 return success 168} 169 170// ShouldNotBeBlank receives exactly 1 string parameter and ensures that it is equal to "". 171func ShouldNotBeBlank(actual interface{}, expected ...interface{}) string { 172 if fail := need(0, expected); fail != success { 173 return fail 174 } 175 value, ok := actual.(string) 176 if !ok { 177 return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) 178 } 179 if value == "" { 180 return shouldNotHaveBeenBlank 181 } 182 return success 183} 184 185// ShouldEqualWithout receives exactly 3 string parameters and ensures that the first is equal to the second 186// after removing all instances of the third from the first using strings.Replace(first, third, "", -1). 187func ShouldEqualWithout(actual interface{}, expected ...interface{}) string { 188 if fail := need(2, expected); fail != success { 189 return fail 190 } 191 actualString, ok1 := actual.(string) 192 expectedString, ok2 := expected[0].(string) 193 replace, ok3 := expected[1].(string) 194 195 if !ok1 || !ok2 || !ok3 { 196 return fmt.Sprintf(shouldAllBeStrings, []reflect.Type{ 197 reflect.TypeOf(actual), 198 reflect.TypeOf(expected[0]), 199 reflect.TypeOf(expected[1]), 200 }) 201 } 202 203 replaced := strings.Replace(actualString, replace, "", -1) 204 if replaced == expectedString { 205 return "" 206 } 207 208 return fmt.Sprintf("Expected '%s' to equal '%s' but without any '%s' (but it didn't).", actualString, expectedString, replace) 209} 210 211// ShouldEqualTrimSpace receives exactly 2 string parameters and ensures that the first is equal to the second 212// after removing all leading and trailing whitespace using strings.TrimSpace(first). 213func ShouldEqualTrimSpace(actual interface{}, expected ...interface{}) string { 214 if fail := need(1, expected); fail != success { 215 return fail 216 } 217 218 actualString, valueIsString := actual.(string) 219 _, value2IsString := expected[0].(string) 220 221 if !valueIsString || !value2IsString { 222 return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) 223 } 224 225 actualString = strings.TrimSpace(actualString) 226 return ShouldEqual(actualString, expected[0]) 227} 228