OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, 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 /// Unit tests for doc. | |
6 library dartdocTests; | |
7 | |
8 import 'dart:async'; | |
9 import 'dart:io'; | |
10 | |
11 import 'package:path/path.dart' as path; | |
12 import 'package:unittest/unittest.dart'; | |
13 | |
14 // TODO(rnystrom): Use "package:" URL (#4968). | |
15 import '../lib/dartdoc.dart' as dd; | |
16 import '../lib/markdown.dart'; | |
17 import 'markdown_test.dart'; | |
18 | |
19 main() { | |
20 // Some tests take more than the default 20 second unittest timeout. | |
21 unittestConfiguration.timeout = null; | |
22 group('isAbsolute', () { | |
23 final doc = new dd.Dartdoc(); | |
24 | |
25 test('returns false if there is no scheme', () { | |
26 expect(doc.isAbsolute('index.html'), isFalse); | |
27 expect(doc.isAbsolute('foo/index.html'), isFalse); | |
28 expect(doc.isAbsolute('foo/bar/index.html'), isFalse); | |
29 }); | |
30 | |
31 test('returns true if there is a scheme', () { | |
32 expect(doc.isAbsolute('http://google.com'), isTrue); | |
33 expect(doc.isAbsolute('hTtPs://google.com'), isTrue); | |
34 expect(doc.isAbsolute('mailto:fake@email.com'), isTrue); | |
35 }); | |
36 }); | |
37 | |
38 group('relativePath', () { | |
39 final doc = new dd.Dartdoc(); | |
40 | |
41 test('absolute path is unchanged', () { | |
42 doc.startFile('dir/sub/file.html'); | |
43 expect(doc.relativePath('http://foo.com'), equals('http://foo.com')); | |
44 }); | |
45 | |
46 test('from root to root', () { | |
47 doc.startFile('root.html'); | |
48 expect(doc.relativePath('other.html'), equals('other.html')); | |
49 }); | |
50 | |
51 test('from root to directory', () { | |
52 doc.startFile('root.html'); | |
53 expect(doc.relativePath('dir/file.html'), equals('dir/file.html')); | |
54 }); | |
55 | |
56 test('from root to nested', () { | |
57 doc.startFile('root.html'); | |
58 expect(doc.relativePath('dir/sub/file.html'), equals( | |
59 'dir/sub/file.html')); | |
60 }); | |
61 | |
62 test('from directory to root', () { | |
63 doc.startFile('dir/file.html'); | |
64 expect(doc.relativePath('root.html'), equals('../root.html')); | |
65 }); | |
66 | |
67 test('from nested to root', () { | |
68 doc.startFile('dir/sub/file.html'); | |
69 expect(doc.relativePath('root.html'), equals('../../root.html')); | |
70 }); | |
71 | |
72 test('from dir to dir with different path', () { | |
73 doc.startFile('dir/file.html'); | |
74 expect(doc.relativePath('other/file.html'), equals('../other/file.html')); | |
75 }); | |
76 | |
77 test('from nested to nested with different path', () { | |
78 doc.startFile('dir/sub/file.html'); | |
79 expect(doc.relativePath('other/sub/file.html'), equals( | |
80 '../../other/sub/file.html')); | |
81 }); | |
82 | |
83 test('from nested to directory with different path', () { | |
84 doc.startFile('dir/sub/file.html'); | |
85 expect(doc.relativePath('other/file.html'), equals( | |
86 '../../other/file.html')); | |
87 }); | |
88 }); | |
89 | |
90 group('dartdoc markdown', () { | |
91 group('[::] blocks', () { | |
92 | |
93 validateDartdocMarkdown('simple case', ''' | |
94 before [:source:] after | |
95 ''', ''' | |
96 <p>before <code>source</code> after</p> | |
97 '''); | |
98 | |
99 validateDartdocMarkdown('unmatched [:', ''' | |
100 before [: after | |
101 ''', ''' | |
102 <p>before [: after</p> | |
103 '''); | |
104 validateDartdocMarkdown('multiple spans in one text', ''' | |
105 a [:one:] b [:two:] c | |
106 ''', ''' | |
107 <p>a <code>one</code> b <code>two</code> c</p> | |
108 '''); | |
109 | |
110 validateDartdocMarkdown('multi-line', ''' | |
111 before [:first | |
112 second:] after | |
113 ''', ''' | |
114 <p>before <code>first | |
115 second</code> after</p> | |
116 '''); | |
117 | |
118 validateDartdocMarkdown('contain backticks', ''' | |
119 before [:can `contain` backticks:] after | |
120 ''', ''' | |
121 <p>before <code>can `contain` backticks</code> after</p> | |
122 '''); | |
123 | |
124 validateDartdocMarkdown('contain double backticks', ''' | |
125 before [:can ``contain`` backticks:] after | |
126 ''', ''' | |
127 <p>before <code>can ``contain`` backticks</code> after</p> | |
128 '''); | |
129 | |
130 validateDartdocMarkdown('contain backticks with spaces', ''' | |
131 before [: `tick` :] after | |
132 ''', ''' | |
133 <p>before <code>`tick`</code> after</p> | |
134 '''); | |
135 | |
136 validateDartdocMarkdown('multiline with spaces', ''' | |
137 before [:in `tick` | |
138 another:] after | |
139 ''', ''' | |
140 <p>before <code>in `tick` | |
141 another</code> after</p> | |
142 '''); | |
143 | |
144 validateDartdocMarkdown('ignore markup inside code', ''' | |
145 before [:*b* _c_:] after | |
146 ''', ''' | |
147 <p>before <code>*b* _c_</code> after</p> | |
148 '''); | |
149 | |
150 validateDartdocMarkdown('escape HTML characters', ''' | |
151 [:<&>:] | |
152 ''', ''' | |
153 <p><code><&></code></p> | |
154 '''); | |
155 | |
156 validateDartdocMarkdown('escape HTML tags', ''' | |
157 '*' [:<em>:] | |
158 ''', ''' | |
159 <p>'*' <code><em></code></p> | |
160 '''); | |
161 }); | |
162 }); | |
163 | |
164 group('integration tests', () { | |
165 test('no entrypoints', () { | |
166 _testRunDartDoc([], (result) { | |
167 expect(result.exitCode, 1); | |
168 }); | |
169 }); | |
170 | |
171 test('entrypoint in lib', () { | |
172 _testRunDartDoc(['test_files/lib/no_package_test_file.dart'], (result) { | |
173 expect(result.exitCode, 0); | |
174 _expectDocumented(result.stdout, libCount: 1, typeCount: 1, memberCount:
0); | |
175 }); | |
176 }); | |
177 | |
178 test('entrypoint somewhere with packages locally', () { | |
179 _testRunDartDoc(['test_files/package_test_file.dart'], (result) { | |
180 expect(result.exitCode, 0); | |
181 _expectDocumented(result.stdout, libCount: 1, typeCount: 1, memberCount:
0); | |
182 }); | |
183 }); | |
184 | |
185 test('file does not exist', () { | |
186 _testRunDartDoc(['test_files/this_file_does_not_exist.dart'], (result) { | |
187 expect(result.exitCode, 1); | |
188 }); | |
189 }); | |
190 }); | |
191 } | |
192 | |
193 void _testRunDartDoc(List<String> libraryPaths, void eval(ProcessResult)) { | |
194 expect(_runDartdoc(libraryPaths).then(eval), completes); | |
195 } | |
196 | |
197 /// The path to the root directory of the dartdoc entrypoint. | |
198 String get _dartdocDir { | |
199 var dir = path.absolute(Platform.script.toFilePath()); | |
200 while (path.basename(dir) != 'dartdoc') { | |
201 if (!path.absolute(dir).contains('dartdoc') || dir == path.dirname(dir)) { | |
202 fail('Unable to find root dartdoc directory.'); | |
203 } | |
204 dir = path.dirname(dir); | |
205 } | |
206 return path.absolute(dir); | |
207 } | |
208 | |
209 /// The path to use for the package root for subprocesses. | |
210 String get _packageRoot { | |
211 var sdkVersionPath = path.join(_dartdocDir, '..', '..', '..', 'version'); | |
212 if (new File(sdkVersionPath).existsSync()) { | |
213 // It looks like dartdoc is being run from the SDK, so we should set the | |
214 // package root to the SDK's packages directory. | |
215 return path.absolute(path.join(_dartdocDir, '..', '..', '..', 'packages')); | |
216 } | |
217 | |
218 // It looks like Dartdoc is being run from the Dart repo, so the package root | |
219 // is in the build output directory. We can find that directory relative to | |
220 // the Dart executable, but that could be in one of two places: in | |
221 // "$BUILD/dart" or "$BUILD/dart-sdk/bin/dart". | |
222 var executableDir = path.dirname(Platform.executable); | |
223 if (new Directory(path.join(executableDir, 'dart-sdk')).existsSync()) { | |
224 // The executable is in "$BUILD/dart". | |
225 return path.absolute(path.join(executableDir, 'packages')); | |
226 } else { | |
227 // The executable is in "$BUILD/dart-sdk/bin/dart". | |
228 return path.absolute(path.join(executableDir, '..', '..', 'packages')); | |
229 } | |
230 } | |
231 | |
232 /// Runs dartdoc with the libraryPaths provided, and completes to dartdoc's | |
233 /// ProcessResult. | |
234 Future<ProcessResult> _runDartdoc(List<String> libraryPaths) { | |
235 var dartBin = Platform.executable; | |
236 | |
237 var dartdoc = path.join(_dartdocDir, 'bin/dartdoc.dart'); | |
238 | |
239 final runArgs = ['--package-root=$_packageRoot/', dartdoc]; | |
240 | |
241 // Turn relative libraryPaths to absolute ones. | |
242 runArgs.addAll(libraryPaths | |
243 .map((e) => path.join(path.absolute(dd.scriptDir), e))); | |
244 | |
245 return Process.run(dartBin, runArgs); | |
246 } | |
247 | |
248 final _dartdocCompletionRegExp = | |
249 new RegExp(r'Documentation complete -- documented (\d+) libraries, (\d+) types
, and (\d+) members\.'); | |
250 | |
251 void _expectDocumented(String output, { int libCount, int typeCount, | |
252 int memberCount}) { | |
253 | |
254 final completionMatches = _dartdocCompletionRegExp.allMatches(output) | |
255 .toList(); | |
256 | |
257 expect(completionMatches, hasLength(1), | |
258 reason: 'dartdoc output should contain one summary'); | |
259 | |
260 final completionMatch = completionMatches.single; | |
261 | |
262 if(libCount != null) { | |
263 expect(int.parse(completionMatch[1]), libCount, | |
264 reason: 'expected library count'); | |
265 } | |
266 | |
267 if(typeCount != null) { | |
268 expect(int.parse(completionMatch[2]), typeCount, | |
269 reason: 'expected type count'); | |
270 } | |
271 | |
272 if(memberCount != null) { | |
273 expect(int.parse(completionMatch[3]), memberCount, | |
274 reason: 'expected member count'); | |
275 } | |
276 } | |
277 | |
278 | |
279 validateDartdocMarkdown(String description, String markdown, | |
280 String html) { | |
281 var dartdoc = new dd.Dartdoc(); | |
282 validate(description, markdown, html, linkResolver: dartdoc.dartdocResolver, | |
283 inlineSyntaxes: dartdoc.dartdocSyntaxes); | |
284 } | |
OLD | NEW |