OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'dart:async'; | |
6 import 'dart:convert'; | |
7 | |
8 import 'package:http/http.dart' as http; | |
9 import 'package:http/testing.dart'; | |
10 import 'package:path/path.dart' as path; | |
11 import 'package:scheduled_test/scheduled_test.dart'; | |
12 | |
13 import '../../lib/src/entrypoint.dart'; | |
14 import '../../lib/src/validator.dart'; | |
15 import '../../lib/src/validator/dependency.dart'; | |
16 import '../descriptor.dart' as d; | |
17 import '../test_pub.dart'; | |
18 import 'utils.dart'; | |
19 | |
20 Validator dependency(Entrypoint entrypoint) => | |
21 new DependencyValidator(entrypoint); | |
22 | |
23 expectDependencyValidationError(String error) { | |
24 expect(schedulePackageValidation(dependency), | |
25 completion(pairOf(anyElement(contains(error)), isEmpty))); | |
26 } | |
27 | |
28 expectDependencyValidationWarning(String warning) { | |
29 expect(schedulePackageValidation(dependency), | |
30 completion(pairOf(isEmpty, anyElement(contains(warning))))); | |
31 } | |
32 | |
33 /// Sets up a test package with dependency [dep] and mocks a server with | |
34 /// [hostedVersions] of the package available. | |
35 setUpDependency(Map dep, {List<String> hostedVersions}) { | |
36 useMockClient(new MockClient((request) { | |
37 expect(request.method, equals("GET")); | |
38 expect(request.url.path, equals("/api/packages/foo")); | |
39 | |
40 if (hostedVersions == null) { | |
41 return new Future.value(new http.Response("not found", 404)); | |
42 } else { | |
43 return new Future.value(new http.Response(JSON.encode({ | |
44 "name": "foo", | |
45 "uploaders": ["nweiz@google.com"], | |
46 "versions": hostedVersions.map((version) => | |
47 packageVersionApiMap(packageMap('foo', version))).toList() | |
48 }), 200)); | |
49 } | |
50 })); | |
51 | |
52 d.dir(appPath, [ | |
53 d.libPubspec("test_pkg", "1.0.0", deps: {"foo": dep}) | |
54 ]).create(); | |
55 } | |
56 | |
57 main() { | |
58 initConfig(); | |
59 | |
60 group('should consider a package valid if it', () { | |
61 integration('looks normal', () { | |
62 d.validPackage.create(); | |
63 expectNoValidationError(dependency); | |
64 }); | |
65 | |
66 integration('has a ^ constraint with an appropriate SDK constraint', () { | |
67 d.dir(appPath, [ | |
68 d.libPubspec("test_pkg", "1.0.0", deps: { | |
69 "foo": "^1.2.3" | |
70 }, sdk: ">=1.8.0 <2.0.0") | |
71 ]).create(); | |
72 expectNoValidationError(dependency); | |
73 }); | |
74 }); | |
75 | |
76 group('should consider a package invalid if it', () { | |
77 setUp(d.validPackage.create); | |
78 | |
79 group('has a git dependency', () { | |
80 group('where a hosted version exists', () { | |
81 integration("and should suggest the hosted primary version", () { | |
82 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, | |
83 hostedVersions: ["3.0.0-pre", "2.0.0", "1.0.0"]); | |
84 expectDependencyValidationWarning(' foo: ">=2.0.0 <3.0.0"'); | |
85 }); | |
86 | |
87 integration("and should suggest the hosted prerelease version if " | |
88 "it's the only version available", () { | |
89 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, | |
90 hostedVersions: ["3.0.0-pre", "2.0.0-pre"]); | |
91 expectDependencyValidationWarning(' foo: ">=3.0.0-pre <4.0.0"'); | |
92 }); | |
93 | |
94 integration("and should suggest a tighter constraint if primary is " | |
95 "pre-1.0.0", () { | |
96 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, | |
97 hostedVersions: ["0.0.1", "0.0.2"]); | |
98 expectDependencyValidationWarning(' foo: ">=0.0.2 <0.1.0"'); | |
99 }); | |
100 }); | |
101 | |
102 group('where no hosted version exists', () { | |
103 integration("and should use the other source's version", () { | |
104 setUpDependency({ | |
105 'git': 'git://github.com/dart-lang/foo', | |
106 'version': '>=1.0.0 <2.0.0' | |
107 }); | |
108 expectDependencyValidationWarning(' foo: ">=1.0.0 <2.0.0"'); | |
109 }); | |
110 | |
111 integration("and should use the other source's unquoted version if " | |
112 "concrete", () { | |
113 setUpDependency({ | |
114 'git': 'git://github.com/dart-lang/foo', | |
115 'version': '0.2.3' | |
116 }); | |
117 expectDependencyValidationWarning(' foo: 0.2.3'); | |
118 }); | |
119 }); | |
120 }); | |
121 | |
122 group('has a path dependency', () { | |
123 group('where a hosted version exists', () { | |
124 integration("and should suggest the hosted primary version", () { | |
125 setUpDependency({'path': path.join(sandboxDir, 'foo')}, | |
126 hostedVersions: ["3.0.0-pre", "2.0.0", "1.0.0"]); | |
127 expectDependencyValidationError(' foo: ">=2.0.0 <3.0.0"'); | |
128 }); | |
129 | |
130 integration("and should suggest the hosted prerelease version if " | |
131 "it's the only version available", () { | |
132 setUpDependency({'path': path.join(sandboxDir, 'foo')}, | |
133 hostedVersions: ["3.0.0-pre", "2.0.0-pre"]); | |
134 expectDependencyValidationError(' foo: ">=3.0.0-pre <4.0.0"'); | |
135 }); | |
136 | |
137 integration("and should suggest a tighter constraint if primary is " | |
138 "pre-1.0.0", () { | |
139 setUpDependency({'path': path.join(sandboxDir, 'foo')}, | |
140 hostedVersions: ["0.0.1", "0.0.2"]); | |
141 expectDependencyValidationError(' foo: ">=0.0.2 <0.1.0"'); | |
142 }); | |
143 }); | |
144 | |
145 group('where no hosted version exists', () { | |
146 integration("and should use the other source's version", () { | |
147 setUpDependency({ | |
148 'path': path.join(sandboxDir, 'foo'), | |
149 'version': '>=1.0.0 <2.0.0' | |
150 }); | |
151 expectDependencyValidationError(' foo: ">=1.0.0 <2.0.0"'); | |
152 }); | |
153 | |
154 integration("and should use the other source's unquoted version if " | |
155 "concrete", () { | |
156 setUpDependency({ | |
157 'path': path.join(sandboxDir, 'foo'), | |
158 'version': '0.2.3' | |
159 }); | |
160 expectDependencyValidationError(' foo: 0.2.3'); | |
161 }); | |
162 }); | |
163 }); | |
164 | |
165 group('has an unconstrained dependency', () { | |
166 group('and it should not suggest a version', () { | |
167 integration("if there's no lockfile", () { | |
168 d.dir(appPath, [ | |
169 d.libPubspec("test_pkg", "1.0.0", deps: { | |
170 "foo": "any" | |
171 }) | |
172 ]).create(); | |
173 | |
174 expect(schedulePackageValidation(dependency), completion( | |
175 pairOf(isEmpty, everyElement(isNot(contains("\n foo:")))))); | |
176 }); | |
177 | |
178 integration("if the lockfile doesn't have an entry for the " | |
179 "dependency", () { | |
180 d.dir(appPath, [ | |
181 d.libPubspec("test_pkg", "1.0.0", deps: { | |
182 "foo": "any" | |
183 }), | |
184 d.file("pubspec.lock", JSON.encode({ | |
185 'packages': { | |
186 'bar': { | |
187 'version': '1.2.3', | |
188 'source': 'hosted', | |
189 'description': { | |
190 'name': 'bar', | |
191 'url': 'http://pub.dartlang.org' | |
192 } | |
193 } | |
194 } | |
195 })) | |
196 ]).create(); | |
197 | |
198 expect(schedulePackageValidation(dependency), completion( | |
199 pairOf(isEmpty, everyElement(isNot(contains("\n foo:")))))); | |
200 }); | |
201 }); | |
202 | |
203 group('with a lockfile', () { | |
204 integration('and it should suggest a constraint based on the locked ' | |
205 'version', () { | |
206 d.dir(appPath, [ | |
207 d.libPubspec("test_pkg", "1.0.0", deps: { | |
208 "foo": "any" | |
209 }), | |
210 d.file("pubspec.lock", JSON.encode({ | |
211 'packages': { | |
212 'foo': { | |
213 'version': '1.2.3', | |
214 'source': 'hosted', | |
215 'description': { | |
216 'name': 'foo', | |
217 'url': 'http://pub.dartlang.org' | |
218 } | |
219 } | |
220 } | |
221 })) | |
222 ]).create(); | |
223 | |
224 expectDependencyValidationWarning(' foo: ">=1.2.3 <2.0.0"'); | |
225 }); | |
226 | |
227 integration('and it should suggest a concrete constraint if the locked ' | |
228 'version is pre-1.0.0', () { | |
229 d.dir(appPath, [ | |
230 d.libPubspec("test_pkg", "1.0.0", deps: { | |
231 "foo": "any" | |
232 }), | |
233 d.file("pubspec.lock", JSON.encode({ | |
234 'packages': { | |
235 'foo': { | |
236 'version': '0.1.2', | |
237 'source': 'hosted', | |
238 'description': { | |
239 'name': 'foo', | |
240 'url': 'http://pub.dartlang.org' | |
241 } | |
242 } | |
243 } | |
244 })) | |
245 ]).create(); | |
246 | |
247 expectDependencyValidationWarning(' foo: ">=0.1.2 <0.2.0"'); | |
248 }); | |
249 }); | |
250 }); | |
251 | |
252 integration('with a single-version dependency and it should suggest a ' | |
253 'constraint based on the version', () { | |
254 d.dir(appPath, [ | |
255 d.libPubspec("test_pkg", "1.0.0", deps: { | |
256 "foo": "1.2.3" | |
257 }) | |
258 ]).create(); | |
259 | |
260 expectDependencyValidationWarning(' foo: ">=1.2.3 <2.0.0"'); | |
261 }); | |
262 | |
263 group('has a dependency without a lower bound', () { | |
264 group('and it should not suggest a version', () { | |
265 integration("if there's no lockfile", () { | |
266 d.dir(appPath, [ | |
267 d.libPubspec("test_pkg", "1.0.0", deps: { | |
268 "foo": "<3.0.0" | |
269 }) | |
270 ]).create(); | |
271 | |
272 expect(schedulePackageValidation(dependency), completion( | |
273 pairOf(isEmpty, everyElement(isNot(contains("\n foo:")))))); | |
274 }); | |
275 | |
276 integration("if the lockfile doesn't have an entry for the " | |
277 "dependency", () { | |
278 d.dir(appPath, [ | |
279 d.libPubspec("test_pkg", "1.0.0", deps: { | |
280 "foo": "<3.0.0" | |
281 }), | |
282 d.file("pubspec.lock", JSON.encode({ | |
283 'packages': { | |
284 'bar': { | |
285 'version': '1.2.3', | |
286 'source': 'hosted', | |
287 'description': { | |
288 'name': 'bar', | |
289 'url': 'http://pub.dartlang.org' | |
290 } | |
291 } | |
292 } | |
293 })) | |
294 ]).create(); | |
295 | |
296 expect(schedulePackageValidation(dependency), completion( | |
297 pairOf(isEmpty, everyElement(isNot(contains("\n foo:")))))); | |
298 }); | |
299 }); | |
300 | |
301 group('with a lockfile', () { | |
302 integration('and it should suggest a constraint based on the locked ' | |
303 'version', () { | |
304 d.dir(appPath, [ | |
305 d.libPubspec("test_pkg", "1.0.0", deps: { | |
306 "foo": "<3.0.0" | |
307 }), | |
308 d.file("pubspec.lock", JSON.encode({ | |
309 'packages': { | |
310 'foo': { | |
311 'version': '1.2.3', | |
312 'source': 'hosted', | |
313 'description': { | |
314 'name': 'foo', | |
315 'url': 'http://pub.dartlang.org' | |
316 } | |
317 } | |
318 } | |
319 })) | |
320 ]).create(); | |
321 | |
322 expectDependencyValidationWarning(' foo: ">=1.2.3 <3.0.0"'); | |
323 }); | |
324 | |
325 integration('and it should preserve the upper-bound operator', () { | |
326 d.dir(appPath, [ | |
327 d.libPubspec("test_pkg", "1.0.0", deps: { | |
328 "foo": "<=3.0.0" | |
329 }), | |
330 d.file("pubspec.lock", JSON.encode({ | |
331 'packages': { | |
332 'foo': { | |
333 'version': '1.2.3', | |
334 'source': 'hosted', | |
335 'description': { | |
336 'name': 'foo', | |
337 'url': 'http://pub.dartlang.org' | |
338 } | |
339 } | |
340 } | |
341 })) | |
342 ]).create(); | |
343 | |
344 expectDependencyValidationWarning(' foo: ">=1.2.3 <=3.0.0"'); | |
345 }); | |
346 | |
347 integration('and it should expand the suggested constraint if the ' | |
348 'locked version matches the upper bound', () { | |
349 d.dir(appPath, [ | |
350 d.libPubspec("test_pkg", "1.0.0", deps: { | |
351 "foo": "<=1.2.3" | |
352 }), | |
353 d.file("pubspec.lock", JSON.encode({ | |
354 'packages': { | |
355 'foo': { | |
356 'version': '1.2.3', | |
357 'source': 'hosted', | |
358 'description': { | |
359 'name': 'foo', | |
360 'url': 'http://pub.dartlang.org' | |
361 } | |
362 } | |
363 } | |
364 })) | |
365 ]).create(); | |
366 | |
367 expectDependencyValidationWarning(' foo: ">=1.2.3 <2.0.0"'); | |
368 }); | |
369 }); | |
370 }); | |
371 | |
372 group('with a dependency without an upper bound', () { | |
373 integration('and it should suggest a constraint based on the lower bound', | |
374 () { | |
375 d.dir(appPath, [ | |
376 d.libPubspec("test_pkg", "1.0.0", deps: { | |
377 "foo": ">=1.2.3" | |
378 }) | |
379 ]).create(); | |
380 | |
381 expectDependencyValidationWarning(' foo: ">=1.2.3 <2.0.0"'); | |
382 }); | |
383 | |
384 integration('and it should preserve the lower-bound operator', () { | |
385 d.dir(appPath, [ | |
386 d.libPubspec("test_pkg", "1.0.0", deps: { | |
387 "foo": ">1.2.3" | |
388 }) | |
389 ]).create(); | |
390 | |
391 expectDependencyValidationWarning(' foo: ">1.2.3 <2.0.0"'); | |
392 }); | |
393 }); | |
394 | |
395 group('has a ^ dependency', () { | |
396 integration("without an SDK constraint", () { | |
397 d.dir(appPath, [ | |
398 d.libPubspec("integration_pkg", "1.0.0", deps: { | |
399 "foo": "^1.2.3" | |
400 }) | |
401 ]).create(); | |
402 | |
403 expectDependencyValidationError(' foo: ">=1.2.3 <2.0.0"'); | |
404 }); | |
405 | |
406 integration("with a too-broad SDK constraint", () { | |
407 d.dir(appPath, [ | |
408 d.libPubspec("test_pkg", "1.0.0", deps: { | |
409 "foo": "^1.2.3" | |
410 }, sdk: ">=1.5.0 <2.0.0") | |
411 ]).create(); | |
412 | |
413 expectDependencyValidationError(' foo: ">=1.2.3 <2.0.0"'); | |
414 }); | |
415 }); | |
416 }); | |
417 } | |
OLD | NEW |