1/*
2 * Copyright 2001-2008 Artima, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.scalatest.matchers
17
18import org.scalatest._
19import org.scalatest.prop.Checkers
20import org.scalacheck._
21import Arbitrary._
22import Prop._
23
24class ShouldStartWithSubstringSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion {
25
26  describe("The startWith substring syntax") {
27
28    it("should do nothing if the string starts with the specified substring") {
29
30      "1.78" should startWith ("1.7")
31      "21.7" should startWith ("2")
32      "21.78" should startWith ("21.78")
33      check((s: String, t: String) => returnsNormally(s + t should startWith (s)))
34    }
35
36    it("should do nothing if the string does not start with the specified substring when used with not") {
37
38      "eight" should not { startWith ("1.7") }
39      "eight" should not startWith ("1.7")
40      check((s: String, t: String) => (s + t).indexOf(t) != 0 ==> returnsNormally(s + t should not (startWith (t))))
41      check((s: String, t: String) => (s + t).indexOf(t) != 0 ==> returnsNormally(s + t should not startWith (t)))
42    }
43
44    it("should do nothing if the string does not start with the specified substring when used in a logical-and expression") {
45
46      "1.7b" should (startWith ("1.7") and (startWith ("1.7b")))
47      "1.7b" should ((startWith ("1.7")) and (startWith ("1.7b")))
48      "1.7b" should (startWith ("1.7") and startWith ("1.7b"))
49
50      check((s: String, t: String) => returnsNormally(s + t should (startWith (s) and startWith (s))))
51    }
52
53    it("should do nothing if the string does not start with the specified substring when used in a logical-or expression") {
54
55      "1.7" should (startWith ("hello") or (startWith ("1")))
56      "1.7" should ((startWith ("hello")) or (startWith ("1")))
57      "1.7" should (startWith ("hello") or startWith ("1"))
58
59      "1.7" should (startWith ("hello") or (startWith ("1.7")))
60      "1.7" should ((startWith ("hello")) or (startWith ("1.7")))
61      "1.7" should (startWith ("hello") or startWith ("1.7"))
62
63      check((s: String, t: String) => returnsNormally(s + t should (startWith ("hi") or startWith (s))))
64    }
65
66    it("should do nothing if the string does not start with the specified substring when used in a logical-and expression with not") {
67      "fred" should (not (startWith ("red")) and not (startWith ("1.7")))
68      "fred" should ((not startWith ("red")) and (not startWith ("1.7")))
69      "fred" should (not startWith ("red") and not startWith ("1.7"))
70      check((s: String) => s.indexOf("bob") != 0 && s.indexOf("1.7") != 0 ==> returnsNormally(s should (not startWith ("bob") and not startWith ("1.7"))))
71    }
72
73    it("should do nothing if the string does not start with the specified substring when used in a logical-or expression with not") {
74      "fred" should (not (startWith ("fred")) or not (startWith ("1.7")))
75      "fred" should ((not startWith ("fred")) or (not startWith ("1.7")))
76      "fred" should (not startWith ("fred") or not startWith ("1.7"))
77      check((s: String) => s.indexOf("a") != 0 || s.indexOf("b") != 0 ==> returnsNormally(s should (not startWith ("a") or not startWith ("b"))))
78    }
79
80    it("should throw TestFailedException if the string does not match substring specified as a string") {
81
82      val caught1 = intercept[TestFailedException] {
83        "1.7" should startWith ("1.78")
84      }
85      assert(caught1.getMessage === "\"1.7\" did not start with substring \"1.78\"")
86
87      val caught2 = intercept[TestFailedException] {
88        "1.7" should startWith ("21.7")
89      }
90      assert(caught2.getMessage === "\"1.7\" did not start with substring \"21.7\"")
91
92      val caught3 = intercept[TestFailedException] {
93        "-one.eight" should startWith ("1.7")
94      }
95      assert(caught3.getMessage === "\"-one.eight\" did not start with substring \"1.7\"")
96
97      val caught6 = intercept[TestFailedException] {
98        "eight" should startWith ("1.7")
99      }
100      assert(caught6.getMessage === "\"eight\" did not start with substring \"1.7\"")
101
102      val caught7 = intercept[TestFailedException] {
103        "one.eight" should startWith ("1.7")
104      }
105      assert(caught7.getMessage === "\"one.eight\" did not start with substring \"1.7\"")
106
107      val caught8 = intercept[TestFailedException] {
108        "onedoteight" should startWith ("1.7")
109      }
110      assert(caught8.getMessage === "\"onedoteight\" did not start with substring \"1.7\"")
111
112      val caught9 = intercept[TestFailedException] {
113        "***" should startWith ("1.7")
114      }
115      assert(caught9.getMessage === "\"***\" did not start with substring \"1.7\"")
116
117      check((s: String) => s.indexOf("1.7") == -1 ==> throwsTestFailedException(s should startWith ("1.7")))
118    }
119
120    it("should throw TestFailedException if the string does matches substring specified as a string when used with not") {
121
122      val caught1 = intercept[TestFailedException] {
123        "1.7" should not { startWith ("1.7") }
124      }
125      assert(caught1.getMessage === "\"1.7\" started with substring \"1.7\"")
126
127      val caught2 = intercept[TestFailedException] {
128        "1.7" should not { startWith ("1.7") }
129      }
130      assert(caught2.getMessage === "\"1.7\" started with substring \"1.7\"")
131
132      val caught3 = intercept[TestFailedException] {
133        "-1.8" should not { startWith ("-1") }
134      }
135      assert(caught3.getMessage === "\"-1.8\" started with substring \"-1\"")
136
137      val caught4 = intercept[TestFailedException] {
138        "8" should not { startWith ("8") }
139      }
140      assert(caught4.getMessage === "\"8\" started with substring \"8\"")
141
142      val caught5 = intercept[TestFailedException] {
143        "1." should not { startWith ("1") }
144      }
145      assert(caught5.getMessage === "\"1.\" started with substring \"1\"")
146
147      val caught11 = intercept[TestFailedException] {
148        "1.7" should not startWith ("1.7")
149      }
150      assert(caught11.getMessage === "\"1.7\" started with substring \"1.7\"")
151
152      val caught13 = intercept[TestFailedException] {
153        "-1.8" should not startWith ("-")
154      }
155      assert(caught13.getMessage === "\"-1.8\" started with substring \"-\"")
156
157      val caught14 = intercept[TestFailedException] {
158        "8" should not startWith ("")
159      }
160      assert(caught14.getMessage === "\"8\" started with substring \"\"")
161
162      val caught15 = intercept[TestFailedException] {
163        "1." should not startWith ("1.")
164      }
165      assert(caught15.getMessage === "\"1.\" started with substring \"1.\"")
166
167      val caught21 = intercept[TestFailedException] {
168        "a1.7" should not { startWith ("a1") }
169      }
170      assert(caught21.getMessage === "\"a1.7\" started with substring \"a1\"")
171
172      val caught22 = intercept[TestFailedException] {
173        "1.7b" should not { startWith ("1.7") }
174      }
175      assert(caught22.getMessage === "\"1.7b\" started with substring \"1.7\"")
176
177      val caught23 = intercept[TestFailedException] {
178        "a-1.8b" should not { startWith ("a-1.8") }
179      }
180      assert(caught23.getMessage === "\"a-1.8b\" started with substring \"a-1.8\"")
181
182      check((s: String) => s.length != 0 ==> throwsTestFailedException(s should not startWith (s.substring(0, 1))))
183    }
184
185    it("should throw TestFailedException if the string starts with the specified substring when used in a logical-and expression") {
186
187      val caught1 = intercept[TestFailedException] {
188        "1.7" should (startWith ("1.7") and (startWith ("1.8")))
189      }
190      assert(caught1.getMessage === "\"1.7\" started with substring \"1.7\", but \"1.7\" did not start with substring \"1.8\"")
191
192      val caught2 = intercept[TestFailedException] {
193        "1.7" should ((startWith ("1")) and (startWith ("1.8")))
194      }
195      assert(caught2.getMessage === "\"1.7\" started with substring \"1\", but \"1.7\" did not start with substring \"1.8\"")
196
197      val caught3 = intercept[TestFailedException] {
198        "1.7" should (startWith ("1.7") and startWith ("1.8"))
199      }
200      assert(caught3.getMessage === "\"1.7\" started with substring \"1.7\", but \"1.7\" did not start with substring \"1.8\"")
201
202      // Check to make sure the error message "short circuits" (i.e., just reports the left side's failure)
203      val caught4 = intercept[TestFailedException] {
204        "one.eight" should (startWith ("1.7") and (startWith ("1.8")))
205      }
206      assert(caught4.getMessage === "\"one.eight\" did not start with substring \"1.7\"")
207
208      val caught5 = intercept[TestFailedException] {
209        "one.eight" should ((startWith ("1.7")) and (startWith ("1.8")))
210      }
211      assert(caught5.getMessage === "\"one.eight\" did not start with substring \"1.7\"")
212
213      val caught6 = intercept[TestFailedException] {
214        "one.eight" should (startWith ("1.7") and startWith ("1.8"))
215      }
216      assert(caught6.getMessage === "\"one.eight\" did not start with substring \"1.7\"")
217
218      check((s: String, t: String, u: String) => (s + u).indexOf(t) != 0 ==> throwsTestFailedException(s + u should (startWith (s) and startWith (t))))
219    }
220
221    it("should throw TestFailedException if the string starts with the specified substring when used in a logical-or expression") {
222
223      val caught1 = intercept[TestFailedException] {
224        "one.seven" should (startWith ("1.7") or (startWith ("1.8")))
225      }
226      assert(caught1.getMessage === "\"one.seven\" did not start with substring \"1.7\", and \"one.seven\" did not start with substring \"1.8\"")
227
228      val caught2 = intercept[TestFailedException] {
229        "one.seven" should ((startWith ("1.7")) or (startWith ("1.8")))
230      }
231      assert(caught2.getMessage === "\"one.seven\" did not start with substring \"1.7\", and \"one.seven\" did not start with substring \"1.8\"")
232
233      val caught3 = intercept[TestFailedException] {
234        "one.seven" should (startWith ("1.7") or startWith ("1.8"))
235      }
236      assert(caught3.getMessage === "\"one.seven\" did not start with substring \"1.7\", and \"one.seven\" did not start with substring \"1.8\"")
237
238      check(
239        (s: String, t: String, u: String, v: String) => {
240          (t.length != 0 && v.length != 0 && (s + u).indexOf(t) != 0 && (s + u).indexOf(v) != 0) ==>
241            throwsTestFailedException(s + u should (startWith (t) or startWith (v)))
242        }
243      )
244    }
245
246    it("should throw TestFailedException if the string starts with the specified substring when used in a logical-and expression used with not") {
247
248      val caught1 = intercept[TestFailedException] {
249        "1.7" should (not startWith ("1.8") and (not startWith ("1.7")))
250      }
251      assert(caught1.getMessage === "\"1.7\" did not start with substring \"1.8\", but \"1.7\" started with substring \"1.7\"")
252
253      val caught2 = intercept[TestFailedException] {
254        "1.7" should ((not startWith ("1.8")) and (not startWith ("1.7")))
255      }
256      assert(caught2.getMessage === "\"1.7\" did not start with substring \"1.8\", but \"1.7\" started with substring \"1.7\"")
257
258      val caught3 = intercept[TestFailedException] {
259        "1.7" should (not startWith ("1.8") and not startWith ("1.7"))
260      }
261      assert(caught3.getMessage === "\"1.7\" did not start with substring \"1.8\", but \"1.7\" started with substring \"1.7\"")
262
263      val caught4 = intercept[TestFailedException] {
264        "a1.7" should (not startWith ("1.8") and (not startWith ("a1.7")))
265      }
266      assert(caught4.getMessage === "\"a1.7\" did not start with substring \"1.8\", but \"a1.7\" started with substring \"a1.7\"")
267
268      val caught5 = intercept[TestFailedException] {
269        "1.7b" should ((not startWith ("1.8")) and (not startWith ("1.7")))
270      }
271      assert(caught5.getMessage === "\"1.7b\" did not start with substring \"1.8\", but \"1.7b\" started with substring \"1.7\"")
272
273      val caught6 = intercept[TestFailedException] {
274        "a1.7b" should (not startWith ("1.8") and not startWith ("a1.7"))
275      }
276      assert(caught6.getMessage === "\"a1.7b\" did not start with substring \"1.8\", but \"a1.7b\" started with substring \"a1.7\"")
277
278      check(
279        (s: String, t: String, u: String) =>
280          (s + t + u).indexOf("hi") != 0 ==>
281            throwsTestFailedException(s + t + u should (not startWith ("hi") and not startWith (s)))
282      )
283    }
284
285    it("should throw TestFailedException if the string starts with the specified substring when used in a logical-or expression used with not") {
286
287      val caught1 = intercept[TestFailedException] {
288        "1.7" should (not startWith ("1.7") or (not startWith ("1.7")))
289      }
290      assert(caught1.getMessage === "\"1.7\" started with substring \"1.7\", and \"1.7\" started with substring \"1.7\"")
291
292      val caught2 = intercept[TestFailedException] {
293        "1.7" should ((not startWith ("1.7")) or (not startWith ("1.7")))
294      }
295      assert(caught2.getMessage === "\"1.7\" started with substring \"1.7\", and \"1.7\" started with substring \"1.7\"")
296
297      val caught3 = intercept[TestFailedException] {
298        "1.7" should (not startWith ("1.7") or not startWith ("1.7"))
299      }
300      assert(caught3.getMessage === "\"1.7\" started with substring \"1.7\", and \"1.7\" started with substring \"1.7\"")
301
302      val caught4 = intercept[TestFailedException] {
303        "1.7" should (not (startWith ("1.7")) or not (startWith ("1.7")))
304      }
305      assert(caught4.getMessage === "\"1.7\" started with substring \"1.7\", and \"1.7\" started with substring \"1.7\"")
306
307      val caught5 = intercept[TestFailedException] {
308        "a1.7" should (not startWith ("a1.") or (not startWith ("a1.7")))
309      }
310      assert(caught5.getMessage === "\"a1.7\" started with substring \"a1.\", and \"a1.7\" started with substring \"a1.7\"")
311
312      val caught6 = intercept[TestFailedException] {
313        "1.7b" should ((not startWith ("1.7")) or (not startWith ("1.7")))
314      }
315      assert(caught6.getMessage === "\"1.7b\" started with substring \"1.7\", and \"1.7b\" started with substring \"1.7\"")
316
317      val caught7 = intercept[TestFailedException] {
318        "a1.7b" should (not startWith ("a1.7") or not startWith ("a1"))
319      }
320      assert(caught7.getMessage === "\"a1.7b\" started with substring \"a1.7\", and \"a1.7b\" started with substring \"a1\"")
321
322      val caught8 = intercept[TestFailedException] {
323        "a1.7b" should (not (startWith ("a1.7")) or not (startWith ("a1")))
324      }
325      assert(caught8.getMessage === "\"a1.7b\" started with substring \"a1.7\", and \"a1.7b\" started with substring \"a1\"")
326
327      check(
328        (s: String, t: String) =>
329          throwsTestFailedException(s + t should (not startWith (s) or not startWith ("")))
330      )
331    }
332  }
333}
334
335