Merge lp:~fenryxo/zim/custom-objects into lp:~jaap.karssenberg/zim/custom-objects
- custom-objects
- Merge into custom-objects
Proposed by
Jiří Janoušek
Status: | Merged |
---|---|
Merged at revision: | 363 |
Proposed branch: | lp:~fenryxo/zim/custom-objects |
Merge into: | lp:~jaap.karssenberg/zim/custom-objects |
Diff against target: |
69216 lines (+18457/-10579) 152 files modified
.bzrignore (+2/-0) CHANGELOG.txt (+35/-2) HACKING/Release_checklist.txt (+27/-13) HACKING/Start.txt (+6/-0) HACKING/Test_Suite.txt (+19/-0) MANIFEST.in (+1/-1) Makefile (+6/-0) README.txt (+1/-1) data/dates.list (+3/-2) data/manual/Help.txt (+1/-0) data/manual/Help/Config_Files.txt (+4/-0) data/manual/Help/Key_Bindings.txt (+82/-81) data/manual/Help/Pages.txt (+6/-0) data/manual/Help/Searching.txt (+9/-0) data/manual/Help/Tags.txt (+13/-0) data/manual/Help/Templates.txt (+27/-15) data/manual/Plugins.txt (+3/-0) data/manual/Plugins/Gnuplot_Editor.txt (+21/-0) data/manual/Plugins/Gnuplot_Editor/gnuplot.gnu (+1/-0) data/manual/Plugins/Spell_Checker.txt (+4/-1) data/manual/Plugins/Tags.txt (+13/-0) data/manual/Plugins/Task_List.txt (+1/-1) data/menubar.xml (+5/-1) data/style.conf (+3/-0) data/templates/_gnuplot.gnu (+5/-0) data/urls.list (+1/-1) debian/changelog (+12/-0) debian/control (+1/-1) debian/pyversions (+1/-1) msgfmt.py (+0/-1) test.py (+29/-129) tests/__init__.py (+316/-193) tests/applications.py (+6/-8) tests/async.py (+31/-1) tests/calendar.py (+5/-6) tests/config.py (+36/-19) tests/daemon.py (+4/-13) tests/data/notebook-wiki.xml (+38/-0) tests/diagrameditor.py (+4/-11) tests/equationeditor.py (+4/-11) tests/export.py (+25/-30) tests/formats.py (+58/-34) tests/fs.py (+44/-16) tests/gui.py (+183/-37) tests/history.py (+5/-3) tests/index.py (+71/-56) tests/inlinecalculator.py (+3/-6) tests/notebook.py (+75/-48) tests/package.py (+70/-26) tests/pageview.py (+105/-101) tests/parsing.py (+1/-1) tests/plugins.py (+7/-4) tests/printtobrowser.py (+4/-6) tests/search.py (+31/-27) tests/stores.py (+43/-16) tests/tags.py (+357/-0) tests/tasklist.py (+19/-10) tests/templates.py (+20/-16) tests/versioncontrol.py (+13/-20) tests/widgets.py (+138/-49) tests/www.py (+5/-7) tools/import-launchpad-translations.py (+1/-1) translations/ca.po (+466/-324) translations/cs.po (+491/-327) translations/da.po (+801/-509) translations/de.po (+496/-324) translations/el.po (+462/-320) translations/en_GB.po (+460/-318) translations/es.po (+505/-332) translations/et.po (+477/-334) translations/fr.po (+491/-323) translations/he.po (+536/-354) translations/hr.po (+4/-4) translations/hu.po (+465/-322) translations/it.po (+514/-347) translations/ja.po (+462/-320) translations/ko.po (+4/-4) translations/nl.po (+493/-321) translations/pl.po (+465/-323) translations/ru.po (+809/-626) translations/sk.po (+464/-327) translations/sl.po (+515/-331) translations/sv.po (+486/-341) translations/tr.po (+469/-326) translations/uk.po (+465/-323) translations/zh_CN.po (+564/-376) translations/zh_TW.po (+464/-322) translations/zim.pot (+481/-344) website/files/zim.css (+1/-0) website/pages/downloads.txt (+1/-1) zim.py (+1/-1) zim/__init__.py (+21/-8) zim/applications.py (+33/-6) zim/async.py (+104/-17) zim/config.py (+47/-15) zim/daemon.py (+9/-9) zim/errors.py (+7/-1) zim/exporter.py (+19/-7) zim/formats/__init__.py (+69/-28) zim/formats/html.py (+2/-0) zim/formats/latex.py (+3/-0) zim/formats/wiki.py (+10/-0) zim/fs.py (+118/-57) zim/gui/__init__.py (+165/-61) zim/gui/applications.py (+3/-3) zim/gui/cleannotebookdialog.py (+2/-2) zim/gui/clipboard.py (+38/-30) zim/gui/customtools.py (+4/-5) zim/gui/exportdialog.py (+4/-4) zim/gui/imagegeneratordialog.py (+2/-2) zim/gui/notebookdialog.py (+59/-60) zim/gui/pageindex.py (+134/-116) zim/gui/pageview.py (+364/-72) zim/gui/pathbar.py (+6/-4) zim/gui/preferencesdialog.py (+78/-20) zim/gui/propertiesdialog.py (+1/-2) zim/gui/searchdialog.py (+1/-1) zim/gui/server.py (+1/-1) zim/gui/widgets.py (+369/-135) zim/history.py (+1/-1) zim/index.py (+546/-80) zim/notebook.py (+430/-179) zim/objectmanager.py (+75/-27) zim/parsing.py (+6/-7) zim/plugins/__init__.py (+26/-15) zim/plugins/attachmentbrowser.py (+13/-13) zim/plugins/calendar.py (+1/-1) zim/plugins/diagrameditor.py (+3/-2) zim/plugins/equationeditor.py (+5/-3) zim/plugins/gnu_r_ploteditor.py (+2/-1) zim/plugins/gnuplot_ploteditor.py (+145/-0) zim/plugins/inlinecalculator.py (+1/-1) zim/plugins/linesorter.py (+106/-0) zim/plugins/linkmap/__init__.py (+10/-2) zim/plugins/linkmap/gui.py (+4/-2) zim/plugins/quicknote.py (+12/-3) zim/plugins/screenshot.py (+4/-3) zim/plugins/sourceview.py (+5/-1) zim/plugins/spell.py (+16/-3) zim/plugins/tags.py (+817/-0) zim/plugins/tasklist.py (+13/-25) zim/plugins/trayicon.py (+55/-26) zim/plugins/versioncontrol/__init__.py (+3/-2) zim/plugins/versioncontrol/bzr.py (+5/-7) zim/search.py (+18/-10) zim/stores/__init__.py (+26/-11) zim/stores/files.py (+25/-5) zim/stores/gjots.py (+3/-3) zim/stores/memory.py (+7/-3) zim/stores/xml.py (+1/-1) zim/templates.py (+10/-11) zim/www.py (+14/-14) |
To merge this branch: | bzr merge lp:~fenryxo/zim/custom-objects |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jaap Karssenberg | Pending | ||
Review via email: mp+63476@code.launchpad.net |
Commit message
Description of the change
Pushing my changes:
* Resolved conflicts with trunk.
* SourceView plugin ported to the new style dependency check.
* Fixed KeyError when fallback object factory is used.
* Fixed bug when export of Code Block failed in non-GUI mode.
* If there is an inactive plugin for an unknown object a button
is shown to activate plugin easily.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2010-05-23 23:14:12 +0000 |
3 | +++ .bzrignore 2011-06-04 21:27:03 +0000 |
4 | @@ -15,6 +15,8 @@ |
5 | ./debian/pycompat |
6 | ./man |
7 | ./html |
8 | +./apidoc |
9 | ./windows/build |
10 | ./windows/version-and-date.nsi |
11 | ./xdg/hicolor |
12 | + |
13 | |
14 | === modified file 'CHANGELOG.txt' |
15 | --- CHANGELOG.txt 2011-02-19 16:27:44 +0000 |
16 | +++ CHANGELOG.txt 2011-06-04 21:27:03 +0000 |
17 | @@ -5,6 +5,37 @@ |
18 | Earlier version numbers for zim correspond to the Perl branch. |
19 | |
20 | |
21 | +=== 0.51 - Thu 28 Apr 2011 === |
22 | +Bug fix release |
23 | +* Fixed a critical bug in the "Add Notebook" prompt for the first notebook on |
24 | + a fresh install and two minor bugs with the ntoebook list - Jiří Janoušek |
25 | + |
26 | + |
27 | +=== 0.51 - Tue 19 Apr 2011 === |
28 | +* Fixed critical bug with resizing images - Stefan Muthers |
29 | +* Fixed bug preventing resizing of text entries in dialogs |
30 | +* Fixed bug disabling auto-completion for page names in dialogs |
31 | +* Fix so cancelling the preferences dialog will also reset plugins |
32 | + - Lisa Vitolo |
33 | +* Fix to switch sensitivity of items in the Edit menu on cursor position |
34 | + - Konstantin Baierer |
35 | +* Fix to handle case where document_root is inside notebook folder |
36 | + - Jiří Janoušek |
37 | +* Fixed support for interwiki links in export |
38 | +* Fixed "Link Map" plugin to actually support clicking on page names in the map |
39 | +* Fixed copy pasting to use plain text by default for external applications |
40 | + added preference to revert to old behavior |
41 | +* Disable <Alt><Space> keybinding due to conflicts with internationalization |
42 | + added hidden preference to get it back if desired |
43 | +* Added support for organizing pages by tags - Fabian Moser |
44 | +* Added feature to zoom font size of the page view on <Ctrl>+ / <Ctrl>- |
45 | + - Konstantin Baierer |
46 | +* Added support for system Trash (using gio if available) |
47 | +* Added Calendar widget to the "Insert Date" dialog |
48 | +* Added plugin to sort selected lines - NorfCran |
49 | +* Added plugin for GNUplot plots - Alessandro Magni |
50 | + |
51 | + |
52 | === 0.50 - Mon 14 Feb 2011 === |
53 | Maintenance release with many bug fixes. Biggest change is the refactoring |
54 | of input forms and dialogs, but this is not very visible to the user. |
55 | @@ -191,9 +222,11 @@ |
56 | * Added a web-based interface to read zim notebooks |
57 | * Task List now supports tags |
58 | * Distinguishing between "move page" and "rename page" |
59 | -* Menu actions like "Rename Page (F2)" now follow the focus and work in the side pane as well |
60 | +* Menu actions like "Rename Page (F2)" now follow the focus and work in the |
61 | + side pane as well |
62 | * Page title can be updated automatically when moving a page |
63 | -* "Link" action behaves more like inserting an object instead of applying formatting |
64 | +* "Link" action behaves more like inserting an object instead of applying |
65 | + formatting |
66 | * File links are now inserted showing only the basename of the file |
67 | * Dialogs spawned from another dialog will pop over it |
68 | * Dialogs remember their window size |
69 | |
70 | === modified file 'HACKING/Release_checklist.txt' |
71 | --- HACKING/Release_checklist.txt 2011-02-19 16:27:44 +0000 |
72 | +++ HACKING/Release_checklist.txt 2011-06-04 21:27:03 +0000 |
73 | @@ -13,34 +13,34 @@ |
74 | |
75 | Merge translations: |
76 | * Request download from launchpad |
77 | -* Merge it with tools/import-launchpad-translations.py |
78 | +* Merge it with ''tools/import-launchpad-translations.py'' |
79 | |
80 | Prepare the package: |
81 | * Set version in ''zim/__init__.py'' |
82 | -* Update CHANGELOG.txt -- see `bzr visualize` for changes |
83 | -* Update debian changes -- run e.g. `debchange -v 0.46` |
84 | +* Update CHANGELOG.txt -- see `''bzr visualize''` for changes |
85 | +* Update debian changes -- run e.g. `''debchange -v 0.46''` |
86 | * Optionally merge branch with website updates since previous release |
87 | * Update version number in website downloads page |
88 | |
89 | Check the package: |
90 | -* `./setup.py sdist` (updates meta data etc.) |
91 | -* `make builddeb` and check `lintian -Ivi ../zim_0.46_i386.changes` |
92 | +* `''./setup.py sdist''` (updates meta data etc.) |
93 | +* `make builddeb` and check `''lintian -Ivi ../zim_0.46_i386.changes''` |
94 | * Test website with ./tools/test_website.py |
95 | -* Run `make clean` and check `bzr st` for any remaining build files |
96 | +* Run `''make clean''` and check `''bzr st''` for any remaining build files |
97 | |
98 | Finalize the revision: |
99 | -* run ./test.py for the last time |
100 | +* run ''./test.py'' for the last time |
101 | |
102 | * commit + tag + push |
103 | |
104 | Build release packages: |
105 | -* `./setup.py sdist` (updates meta data etc.) |
106 | -* `make builddeb` + `make clean` |
107 | -* ./tools/build_website.sh |
108 | +* `''./setup.py sdist''` (updates meta data etc.) |
109 | +* `''make builddeb''` + `''make clean''` |
110 | +* ''./tools/build_website.sh'' |
111 | |
112 | Publish to launchpad PPA: |
113 | -* debuild -S -kB3223C82 |
114 | -* dput ppa:jaap.karssenberg/zim zim_XX_sources.changes |
115 | +* ''debuild -S -kB3223C82'' |
116 | +* ''dput ppa:jaap.karssenberg/zim ../zim_XX_sources.changes'' |
117 | |
118 | Publish the release: |
119 | * Upload website |
120 | @@ -48,5 +48,19 @@ |
121 | * Write release notes |
122 | * Announce on freshmeat |
123 | * Announce on launchpad |
124 | -* Announce on gnome files |
125 | +* ~~Announce on gnome files~~ |
126 | * Announce on mailing list |
127 | + |
128 | + |
129 | +**For snapshots** |
130 | +* `''./setup.py sdist`'' to update build meta data |
131 | +* ''debchange -v 0.50-SNASPSHOT-r359'' |
132 | +* ''debuild -S -kB3223C82'' |
133 | +* ''lintian -Ivi ../zim_0.46_i386.changes'' |
134 | +* ''dput ppa:jaap.karssenberg/zim-snapshots ../zim_XX_sources.changes'' |
135 | + |
136 | +To check version numbering is OK use: |
137 | + |
138 | +''' |
139 | +dpkg --compare-versions "0.51" gt "0.50-SNAPSHOT-r345" && echo OK |
140 | +''' |
141 | |
142 | === modified file 'HACKING/Start.txt' |
143 | --- HACKING/Start.txt 2010-01-31 11:22:31 +0000 |
144 | +++ HACKING/Start.txt 2011-06-04 21:27:03 +0000 |
145 | @@ -24,6 +24,12 @@ |
146 | |
147 | ===== Classes ===== |
148 | |
149 | +**NOTE: the overview below is limitted and partially out of date. To generate a full set of API docs install "epydoc" [1] and run "make epydoc" in the zim source dir** |
150 | + |
151 | +[1] http://epydoc.sourceforge.net/ |
152 | + |
153 | +----- |
154 | + |
155 | Each class has inline documentation, use pydoc to view it. |
156 | The tree below is only a summary, run "dev/class_tree.py" to see |
157 | the full tree. |
158 | |
159 | === added file 'HACKING/Test_Suite.txt' |
160 | --- HACKING/Test_Suite.txt 1970-01-01 00:00:00 +0000 |
161 | +++ HACKING/Test_Suite.txt 2011-06-04 21:27:03 +0000 |
162 | @@ -0,0 +1,19 @@ |
163 | +Content-Type: text/x-zim-wiki |
164 | +Wiki-Format: zim 0.4 |
165 | +Creation-Date: 2011-05-13T23:18:07+02:00 |
166 | + |
167 | +====== Test Suite ====== |
168 | + |
169 | +Zim comes with a full test suite, it can be executed using the "''test.py''" script. See "''test.py --help''" for it's commandline options. |
170 | + |
171 | +It is good practice to run the full suite before committing to a development branch and especially before generating a merge request. This should ensures the new patch doesn't break any existing code. |
172 | + |
173 | +For any but the most trivial fixes test cases should be written to ensure the functionality works as designed and to avoid breaking it again at a later time. You'll surprise how often the same bug comes back after some time if there is now test case is in place to detect it. Some bugs are just waiting to happen again and again. |
174 | + |
175 | +For writing tests have a look at the existing test code or check the documentation for the "unittest" module in the python library. (For python versions < 2.7 we use the "unittest2" module, which backports some new features for older python versions.) |
176 | + |
177 | +A most useful tool for developing tests is looking at test **coverage**. When you run "''test.py''" with the "''--coverage''" option the "coverage" module will be loaded and a set of html pages will be generated in "''./coverage''". In these pages you can see line by line what code is called during the test run and what lines of code go untested. It is hard to really get to 100% coverage, but the target should be to get the coverage above at least 80% for each module. |
178 | + |
179 | +If you added e.g. a new class and wrote a test case for it have a look at the coverage to see what additional tests are needed to cover all code. |
180 | + |
181 | +Of course having full coverage is no guarantee we cover all possible inputs, but looking at coverage combined with writing tests for reported bugs makes a strong test suite. Even if the test suite only catches the most simple bugs that users would see when first using the application it is worth the effort. |
182 | |
183 | === modified file 'MANIFEST.in' |
184 | --- MANIFEST.in 2010-07-22 21:33:10 +0000 |
185 | +++ MANIFEST.in 2011-06-04 21:27:03 +0000 |
186 | @@ -10,7 +10,7 @@ |
187 | recursive-include tools/ * |
188 | recursive-include xdg/ * |
189 | prune xdg/hicolor/ |
190 | -recursive-include po/ * |
191 | +recursive-include translations/ * |
192 | recursive-include cgi-bin/ * |
193 | recursive-include contrib/ * |
194 | recursive-include HACKING/ * |
195 | |
196 | === modified file 'Makefile' |
197 | --- Makefile 2010-06-24 20:27:50 +0000 |
198 | +++ Makefile 2011-06-04 21:27:03 +0000 |
199 | @@ -13,6 +13,7 @@ |
200 | @echo "make source - Create source package" |
201 | @echo "make buildrpm - Generate a rpm package" |
202 | @echo "make builddeb - Generate a deb package" |
203 | + @echo "make epydoc - Generate API docs using 'epydoc'" |
204 | @echo "make clean - Get rid of scratch and byte files" |
205 | |
206 | source: |
207 | @@ -31,6 +32,11 @@ |
208 | dpkg-buildpackage -i -I -rfakeroot |
209 | $(MAKE) -f $(CURDIR)/debian/rules clean |
210 | |
211 | +epydoc: |
212 | + rm -fr ./apidoc |
213 | + epydoc --html zim --graph umlclasstree -o ./apidoc --parse-only --no-private |
214 | + @echo -e '\nAPI docs are available in ./apidoc' |
215 | + |
216 | clean: |
217 | $(PYTHON) setup.py clean |
218 | rm -rf build/ MANIFEST tests/tmp/ locale/ man/ xdg/hicolor |
219 | |
220 | === modified file 'README.txt' |
221 | --- README.txt 2011-02-19 16:27:44 +0000 |
222 | +++ README.txt 2011-06-04 21:27:03 +0000 |
223 | @@ -20,7 +20,7 @@ |
224 | |
225 | ====== COPYRIGHT ====== |
226 | |
227 | -Copyright 2008, 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
228 | +Copyright 2008, 2011 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
229 | |
230 | This program is free software; you can redistribute it and/or modify |
231 | it under the terms of the GNU General Public License as published by |
232 | |
233 | === modified file 'data/dates.list' |
234 | --- data/dates.list 2009-08-15 15:02:30 +0000 |
235 | +++ data/dates.list 2011-06-04 21:27:03 +0000 |
236 | @@ -1,9 +1,10 @@ |
237 | # List with date-time formats used for the |
238 | # "Insert Date eand Time" dialog. |
239 | # See man strftime a description of the format. |
240 | +%x |
241 | %c |
242 | %A %d/%m/%Y |
243 | %A %d/%m/%Y %H:%M |
244 | %A %d %B %Y |
245 | -%x |
246 | -%F |
247 | +[d: %Y-%m-%d] |
248 | +%Y-%m-%d |
249 | |
250 | === modified file 'data/manual/Help.txt' |
251 | --- data/manual/Help.txt 2010-07-08 20:29:24 +0000 |
252 | +++ data/manual/Help.txt 2011-06-04 21:27:03 +0000 |
253 | @@ -13,6 +13,7 @@ |
254 | * [[+Notebooks|Notebooks]] |
255 | * [[+Pages|Pages]] |
256 | * [[+Links|Links]] |
257 | +* [[+Tags|Tags]] |
258 | |
259 | Editing |
260 | * [[+Key Bindings|Key Bindings]] |
261 | |
262 | === modified file 'data/manual/Help/Config_Files.txt' |
263 | --- data/manual/Help/Config_Files.txt 2011-02-14 20:22:50 +0000 |
264 | +++ data/manual/Help/Config_Files.txt 2011-06-04 21:27:03 +0000 |
265 | @@ -30,6 +30,8 @@ |
266 | |
267 | The config file is written automatically when you close zim. So if you want to change it manually you need to close all instances of zim first. |
268 | |
269 | +There is a hidden option here called "''autosave_timeout''" which gives the interval for autosaving in seconds, default is 10. |
270 | + |
271 | ==== Interwiki URL list ==== |
272 | The file ''XDG_DATA/zim/urls.list'' gives a list of urls which are used for the [[Links|interwiki]] function. All files in the XDG_DATA path are read when looking for an url, so you can use XDG_DATA_HOME to overload the installation defaults. |
273 | |
274 | @@ -118,3 +120,5 @@ |
275 | There is a notebook specific config files called "''notebook.zim''" which should be in the notebook folder. This file contains a section "''[Notebook]''" which contains the properties that can be set in the [[properties|properties dialog]]. |
276 | |
277 | There is one hidden property, called "''end_of_line''" which determines the end-of-line convention for files written by zim within the scope of this notebook. The value can be either "''dos''" or "''unix''". For newly created notebooks this value is set depending on the platform on which zim is running. Main purpose of this property is to ensure that a notebook which is shared between e.g. linux and windows machines does not change the full file on every write. When desired the property can be changed manually, which will affect all pages edited after the change. |
278 | + |
279 | +A second hidden option is "''disable_trash''" which defaults to ''False''. If enabled this will cause zim to avoid using the system trash for this notebook, see the section about deleting in [[Pages]]. |
280 | |
281 | === modified file 'data/manual/Help/Key_Bindings.txt' |
282 | --- data/manual/Help/Key_Bindings.txt 2010-01-19 18:41:47 +0000 |
283 | +++ data/manual/Help/Key_Bindings.txt 2011-06-04 21:27:03 +0000 |
284 | @@ -10,103 +10,104 @@ |
285 | |
286 | ''' |
287 | F9 Toggle index visibility |
288 | -alt-space Toggle focus between index and buffer |
289 | +<Ctrl><Space> Toggle focus between index and buffer |
290 | opens side pane if index is invisible |
291 | -ctrl-space Same as ctrl-space - optional see preferences |
292 | -ctrl-tab Focus next inteface element (gtk default) |
293 | -''' |
294 | - |
295 | - |
296 | -''' |
297 | -alt-home Go to the home page |
298 | -alt-left Go one page back in history |
299 | -alt-right Go one page forward in history |
300 | -alt-up Go one page up in the namespace |
301 | -alt-down Go one page down in the namespace |
302 | + (optional see preferences) |
303 | +<Ctrl><Tab> Focus next inteface element (gtk default) |
304 | +''' |
305 | + |
306 | + |
307 | +''' |
308 | +<Alt><Home> Go to the home page |
309 | +<Alt><Left> Go one page back in history |
310 | +<Alt><Right> Go one page forward in history |
311 | +<Alt><Up> Go one page up in the namespace |
312 | +<Alt><Down> Go one page down in the namespace |
313 | (The actual page is choosen by the history) |
314 | -alt-pgup Go to the previous page in the index |
315 | -alt-pgdown Go to the next page in the index |
316 | -alt-D Go to todays page |
317 | -''' |
318 | - |
319 | - |
320 | -''' |
321 | -^Q Quit the application |
322 | -^w Close window |
323 | -''' |
324 | - |
325 | - |
326 | -''' |
327 | -^F Find in the current page |
328 | -^G Find next |
329 | -shift-^G Find previous |
330 | -shift-^F Search in all pages |
331 | -^H Find and Replace |
332 | -''' |
333 | - |
334 | - |
335 | -''' |
336 | -^S Save page (forced) |
337 | -shift-^S Save version... |
338 | -^R Reload page (saves first) |
339 | -^J Jump to page... (either an existing or a new page) |
340 | -''' |
341 | - |
342 | - |
343 | -''' |
344 | -^L Link selected text |
345 | +<Alt><PgUp> Go to the previous page in the index |
346 | +<Alt><PgDown> Go to the next page in the index |
347 | +<Alt>D Go to todays page |
348 | +''' |
349 | + |
350 | + |
351 | +''' |
352 | +<Ctrl>Q Quit the application |
353 | +<Ctrl>w Close window |
354 | +''' |
355 | + |
356 | + |
357 | +''' |
358 | +<Ctrl>F Find in the current page |
359 | +<Ctrl>G Find next |
360 | +<Shift><Ctrl>G Find previous |
361 | +<Shift><Ctrl>F Search in all pages |
362 | +<Ctrl>H Find and Replace |
363 | +''' |
364 | + |
365 | + |
366 | +''' |
367 | +<Ctrl>S Save page (forced) |
368 | +<Shift><Ctrl>S Save version... |
369 | +<Ctrl>R Reload page (saves first) |
370 | +<Ctrl>J Jump to page... (either an existing or a new page) |
371 | +''' |
372 | + |
373 | + |
374 | +''' |
375 | +<Ctrl>L Link selected text |
376 | Follow selected text as link when read-only |
377 | -shift-^L Copy a link to the current page to the clipboard |
378 | +<Shift><Ctrl>L Copy a link to the current page to the clipboard |
379 | In the side pane copies a link to the selected page |
380 | - (Paste this link in a page with ^V) |
381 | -^E Show the "edit link" dialog |
382 | -^D Inserts timestamp |
383 | -''' |
384 | - |
385 | - |
386 | -''' |
387 | -^1..^5 Make selected text a heading |
388 | -^6 Make selected text normal |
389 | -^B Make selected text strong |
390 | -^I Make selected text italic |
391 | -^U Make selected text underline (renders highlighted) |
392 | -^K Make selected text strike-trough |
393 | -^T Make selected text verbatim text (monospace font) |
394 | -''' |
395 | - |
396 | - |
397 | -''' |
398 | -^Z Undo |
399 | -Shift-^Z Redo |
400 | -^Y Redo |
401 | -''' |
402 | - |
403 | - |
404 | -''' |
405 | -shift-^D Show the calendar dialog |
406 | + (Paste this link in a page with <Ctrl>V) |
407 | +<Ctrl>E Show the "edit link" dialog |
408 | +<Ctrl>D Inserts timestamp |
409 | +''' |
410 | + |
411 | + |
412 | +''' |
413 | +<Ctrl>1..<Ctrl>5 Make selected text a heading |
414 | +<Ctrl>9 Make selected text normal |
415 | +<Ctrl>B Make selected text strong |
416 | +<Ctrl>I Make selected text italic |
417 | +<Ctrl>U Make selected text underline (renders highlighted) |
418 | +<Ctrl>K Make selected text strike-trough |
419 | +<Ctrl>T Make selected text verbatim text (monospace font) |
420 | +''' |
421 | + |
422 | + |
423 | +''' |
424 | +<Ctrl>Z Undo |
425 | +<Shift><Ctrl>Z Redo |
426 | +<Ctrl>Y Redo |
427 | +''' |
428 | + |
429 | + |
430 | +''' |
431 | +<Shift><Ctrl>D Show the calendar dialog |
432 | ''' |
433 | |
434 | |
435 | ''' |
436 | F1 Show the manual |
437 | F2 Rename current page |
438 | -F3 Find next (same as ^G) |
439 | -F5 Reload page (same as ^R) |
440 | +F3 Find next (same as <Ctrl>G) |
441 | +<Shift>F3 Find previous (same as <Ctrl>G) |
442 | +F5 Reload page (same as <Ctrl>R) |
443 | F12 Toggle checkbox item to 'OK' |
444 | -Shift-F12 Toggle checkbox item to 'NOK' |
445 | +<Shift>F12 Toggle checkbox item to 'NOK' |
446 | ''' |
447 | |
448 | Also all the usual keybindings apply for the gtk text edit widget, thus bindings like |
449 | -''^C'', ''^X'', ''^V'', ''^A'' etc. work as expected. |
450 | +''<Ctrl>C'', ''<Ctrl>X'', ''<Ctrl>V'', ''<Ctrl>A'' etc. work as expected. |
451 | |
452 | ==== Side pane tree ==== |
453 | The following key bindings works when the tree in the side pane is focussed: |
454 | |
455 | ''' |
456 | -^L Insert a link to the selected page |
457 | -shift-^L Copy the selected page to clipboard |
458 | -^C Copy the selected page to clipboard |
459 | -^F Search in the page list as shown |
460 | +<Ctrl>L Insert a link to the selected page |
461 | +<Shift><Ctrl>L Copy the selected page to clipboard |
462 | +<Ctrl>C Copy the selected page to clipboard |
463 | +<Ctrl>F Search in the page list as shown |
464 | * Expand all |
465 | \ Collapse all |
466 | ''' |
467 | @@ -118,9 +119,9 @@ |
468 | ''' |
469 | * Toggle bullets for selected text |
470 | > Toggle email-style quoting for selected text |
471 | -TAB Indent selected text |
472 | -shift-TAB Un-indents selected text |
473 | -BACKSPACE Un-indents selected text |
474 | +<Tab> Indent selected text |
475 | +<Shift><Tab> Un-indents selected text |
476 | +<Backspace> Un-indents selected text |
477 | ''' |
478 | |
479 | |
480 | |
481 | === modified file 'data/manual/Help/Pages.txt' |
482 | --- data/manual/Help/Pages.txt 2010-01-19 18:41:47 +0000 |
483 | +++ data/manual/Help/Pages.txt 2011-06-04 21:27:03 +0000 |
484 | @@ -32,3 +32,9 @@ |
485 | ===== Jump To Dialog ===== |
486 | This dialog is intended to jump to a specified page. It is actually hardly different from the New Page dialog except that it resolves page names relative to the current page and does not immediately create a new page. However you can always create new pages by jumping to a page that does not yet exist and start editing. |
487 | |
488 | +===== Deleting pages ===== |
489 | +When you select "Delete Page" by default zim will try to trash the page and all it's sub pages and attachments - **that means all files that are in the folder below the text file for the page**. If you deleted something on accident you should be able to recover the data from your system's trash can. After recovering data you probable need to run "Re-build Index" from the "Tools" menu to make sure zim indexes the data again. |
490 | + |
491 | +If zim is not able to move data to the trash can it will offer to delete the data permanently. In this case a dialog is shown to ask for confirmation which includes a detailed list of files to be deleted. |
492 | + |
493 | +If you don't like to use the trash by default (e.g. for notebooks that contain sensitive data) there is an option in the notebook [[Config Files|config file]] to disable the trash. In this case the confirmation dialog will always be shown on "delete page". |
494 | |
495 | === modified file 'data/manual/Help/Searching.txt' |
496 | --- data/manual/Help/Searching.txt 2010-07-20 20:37:06 +0000 |
497 | +++ data/manual/Help/Searching.txt 2011-06-04 21:27:03 +0000 |
498 | @@ -54,6 +54,7 @@ |
499 | Links: |
500 | LinksFrom: |
501 | LinksTo: |
502 | +Tag: |
503 | |
504 | |
505 | === Details === |
506 | @@ -125,6 +126,7 @@ |
507 | **Links:** |
508 | **LinksFrom:** |
509 | **LinksTo:** |
510 | + **Tag:** |
511 | |
512 | For example to only search the page names you can use: |
513 | |
514 | @@ -160,3 +162,10 @@ |
515 | namespace: Date and linksto: Planning |
516 | ''' |
517 | |
518 | +The keyword "Tag" can be used to search for specifc tags like: |
519 | +''' |
520 | + |
521 | +Tag: home |
522 | +''' |
523 | + |
524 | +Note that a simple search for a single word like "''@home''" will automatically be converted to "''Tag: home''" |
525 | |
526 | === added file 'data/manual/Help/Tags.txt' |
527 | --- data/manual/Help/Tags.txt 1970-01-01 00:00:00 +0000 |
528 | +++ data/manual/Help/Tags.txt 2011-06-04 21:27:03 +0000 |
529 | @@ -0,0 +1,13 @@ |
530 | +Content-Type: text/x-zim-wiki |
531 | +Wiki-Format: zim 0.4 |
532 | +Creation-Date: 2011-04-04T21:14:35+02:00 |
533 | + |
534 | +====== Tags ====== |
535 | + |
536 | +Zim supports the use of tags to organize pages. Tags are keywords or labels that are used to categorize pages. |
537 | + |
538 | +Tags can be used anywhere in a page using the "@" prefix. Like this: @example @tags |
539 | + |
540 | +To find context based on tags you can use the [[Searching|Search]] dialog. For example to find all pages tagged with "@example" you can search for "''Tag: example''" or just for "''@example''". Since tags are cached in the index, this search is much quicker than a full text search for random words. |
541 | + |
542 | +There is also a plugin that will add a tag cloud and a page index organized by tag in the side page, see also [[Plugins:Tags]] |
543 | |
544 | === modified file 'data/manual/Help/Templates.txt' |
545 | --- data/manual/Help/Templates.txt 2010-03-03 19:43:13 +0000 |
546 | +++ data/manual/Help/Templates.txt 2011-06-04 21:27:03 +0000 |
547 | @@ -55,20 +55,32 @@ |
548 | Available variables: |
549 | |
550 | ''' |
551 | +zim.version # version of zim |
552 | + |
553 | page.name # complete page name |
554 | page.namespace # namespace |
555 | -page.title # last part of the name of the page |
556 | -page.heading # title or first heading in the page |
557 | -page.body # content of the page |
558 | -page.links # list of vars with a .file and a .name subvar |
559 | -page.backlinks # "" idem "" |
560 | -page.is_index # true for the automatic generated index page |
561 | -prev.name # name of previous page |
562 | -prev.file # file name of previous page |
563 | -next.name # name of next page |
564 | -next.file # file name of next page |
565 | -notebook.root # root dir relative to page file |
566 | -zim.version # version of zim |
567 | -''' |
568 | - |
569 | -The "Title" field contains either the first heading in the page or the page name. If the first header is used, this header is removed from the "Body" field. |
570 | +page.basename # last part of the page name |
571 | +page.title # |
572 | +''' |
573 | +''first heading in the page or the basename'' |
574 | +''page.heading # first heading in the page'' |
575 | +''page.body # content of the page (without the leading heading)'' |
576 | +''page.links # list of page objects for pages linked in this page'' |
577 | +''page.backlinks # ''''list of page objects for pages linking to this page'' |
578 | +''page.properties # dict with page properties'' |
579 | + |
580 | +''# These special pages have the same properties as the 'page' object'' |
581 | +''pages.index # the index page generated when exporting'' |
582 | +''pages.home # the home page'' |
583 | +''pages.next # the next page in the index (if any)'' |
584 | +''pages.previous # the previous page in the index (if any)'' |
585 | + |
586 | +''options # dict where format specific options can be set'' |
587 | + |
588 | +Functions available: |
589 | + |
590 | +''' |
591 | +url(link) # turns a zim link into an URL |
592 | +strftime(template, date) # format a date |
593 | +''' |
594 | + |
595 | |
596 | === modified file 'data/manual/Plugins.txt' |
597 | --- data/manual/Plugins.txt 2010-07-06 20:36:53 +0000 |
598 | +++ data/manual/Plugins.txt 2011-06-04 21:27:03 +0000 |
599 | @@ -6,11 +6,14 @@ |
600 | The following plugins are standard included with zim: |
601 | |
602 | * [[+Calendar|Calendar]] |
603 | +* [[+Tags|Tags]] |
604 | * [[+Diagram Editor|Diagram Editor]] |
605 | * [[+Equation Editor|Equation Editor]] |
606 | * [[+GNU R Plot Editor|GNU R Plot Editor]] |
607 | +* [[+Gnuplot Editor|Gnuplot Editor]] |
608 | * [[+Insert Screenshot|Insert Screenshot]] |
609 | * [[+Insert Symbol|Insert Symbol]] |
610 | +* [[+Inline Calculator|Inline Calculator]] |
611 | * [[+Link Map|Link Map]] |
612 | * [[+Quick Note|Quick Note]] |
613 | * [[+Spell Checker|Spell Checker]] |
614 | |
615 | === added directory 'data/manual/Plugins/Gnuplot_Editor' |
616 | === added file 'data/manual/Plugins/Gnuplot_Editor.txt' |
617 | --- data/manual/Plugins/Gnuplot_Editor.txt 1970-01-01 00:00:00 +0000 |
618 | +++ data/manual/Plugins/Gnuplot_Editor.txt 2011-06-04 21:27:03 +0000 |
619 | @@ -0,0 +1,21 @@ |
620 | +Content-Type: text/x-zim-wiki |
621 | +Wiki-Format: zim 0.4 |
622 | +Creation-Date: 2011-03-28T21:59:01+02:00 |
623 | + |
624 | +====== Gnuplot Editor ====== |
625 | + |
626 | + |
627 | +The Gnuplot editor is, as its name suggests, a simple dialog that allows you to insert plots rendered with gnuplot. |
628 | + |
629 | +**Dependencies:** The plugin requires gnuplot to be installed. |
630 | + |
631 | +===== Syntax ===== |
632 | + |
633 | +{{./gnuplot.png?type=gnuplot}} |
634 | +''' |
635 | + |
636 | +plot sin(x), cos(x) |
637 | +''' |
638 | + |
639 | + |
640 | +See http://www.gnuplot.info/ for more information about gnuplot |
641 | |
642 | === added file 'data/manual/Plugins/Gnuplot_Editor/gnuplot.gnu' |
643 | --- data/manual/Plugins/Gnuplot_Editor/gnuplot.gnu 1970-01-01 00:00:00 +0000 |
644 | +++ data/manual/Plugins/Gnuplot_Editor/gnuplot.gnu 2011-06-04 21:27:03 +0000 |
645 | @@ -0,0 +1,1 @@ |
646 | +plot sin(x), cos(x) |
647 | \ No newline at end of file |
648 | |
649 | === added file 'data/manual/Plugins/Gnuplot_Editor/gnuplot.png' |
650 | Binary files data/manual/Plugins/Gnuplot_Editor/gnuplot.png 1970-01-01 00:00:00 +0000 and data/manual/Plugins/Gnuplot_Editor/gnuplot.png 2011-06-04 21:27:03 +0000 differ |
651 | === modified file 'data/manual/Plugins/Spell_Checker.txt' |
652 | --- data/manual/Plugins/Spell_Checker.txt 2010-05-02 12:46:50 +0000 |
653 | +++ data/manual/Plugins/Spell_Checker.txt 2011-06-04 21:27:03 +0000 |
654 | @@ -5,4 +5,7 @@ |
655 | |
656 | This plugin adds inline spell checking for zim. It has a preference setting to determine the language used for spell checking. If this is not set, the system default is used. |
657 | |
658 | -**Dependencies:** This plugin requires the "gtkspell" library to be installed as well as the Python language bindings for this library. On Ubuntu or Debian systems installing the package "python-gtkspell" (or "python-gnome2-extras" on older releases) will meet these dependencies. |
659 | +**Dependencies:** This plugin requires the "gtkspell" library to be installed as well as the Python language bindings for this library. |
660 | + |
661 | +* On Ubuntu or Debian systems installing the package "python-gtkspell" (or "python-gnome2-extras" on older releases) will meet these dependencies. |
662 | +* On Fedora systems, installing the package "gnome-python2-gtkspell" will meet these dependencies. |
663 | |
664 | === added file 'data/manual/Plugins/Tags.txt' |
665 | --- data/manual/Plugins/Tags.txt 1970-01-01 00:00:00 +0000 |
666 | +++ data/manual/Plugins/Tags.txt 2011-06-04 21:27:03 +0000 |
667 | @@ -0,0 +1,13 @@ |
668 | +Content-Type: text/x-zim-wiki |
669 | +Wiki-Format: zim 0.4 |
670 | +Creation-Date: 2011-04-04T21:14:50+02:00 |
671 | + |
672 | +====== Tags ====== |
673 | + |
674 | +This plugin adds a tag cloud and a page index organized by tags in the side pane. |
675 | + |
676 | +The tag cloud allows toggling the selection of tags that is shown in the page index. The page index can be switched between a flat view, showing all pages that match the filtering criteria, and an ordered view that shows known tags as the top level nodes with pages beneath them. |
677 | + |
678 | +**Dependencies:** This plugin has no additional dependencies. |
679 | + |
680 | +**See also: **[[Help:Tags]] |
681 | |
682 | === modified file 'data/manual/Plugins/Task_List.txt' |
683 | --- data/manual/Plugins/Task_List.txt 2010-05-25 19:47:41 +0000 |
684 | +++ data/manual/Plugins/Task_List.txt 2011-06-04 21:27:03 +0000 |
685 | @@ -35,7 +35,7 @@ |
686 | yyyy/mm/dd yyyy-mm-dd |
687 | ''' |
688 | |
689 | -So you can use e.g. "[d: 5/1]", "[d: 2010-1-5]" or "[d: 5/1/10]". |
690 | +So you can use e.g. "[d: 5/1]", "[d: 2010-1-5]" or "[d: 5/1/10]". (Any other separator character to separate year, month, and day will also work, as long as it is not a number or a letter.) |
691 | |
692 | **Note: **dates are parse in European notation, so "dd/mm", not as "mm/dd" as is customary in the US. Unfortunately there is no way to resolve these unambiguously. |
693 | |
694 | |
695 | === modified file 'data/menubar.xml' |
696 | --- data/menubar.xml 2011-02-14 20:22:50 +0000 |
697 | +++ data/menubar.xml 2011-06-04 21:27:03 +0000 |
698 | @@ -42,7 +42,7 @@ |
699 | <menuitem action='edit_object'/> |
700 | <menuitem action='remove_link'/> |
701 | <separator/> |
702 | - <placeholder name='edit_page'/> |
703 | + <placeholder name='plugin_items'/> |
704 | <separator/> |
705 | <menuitem action='copy_location'/> |
706 | <separator/> |
707 | @@ -72,6 +72,10 @@ |
708 | <separator/> |
709 | <placeholder name='plugin_items'/> |
710 | <separator/> |
711 | + <menuitem action='zoom_in'/> |
712 | + <menuitem action='zoom_out'/> |
713 | + <menuitem action='zoom_reset'/> |
714 | + <separator/> |
715 | <menuitem action='reload_page'/> |
716 | </menu> |
717 | <menu action='insert_menu'> |
718 | |
719 | === modified file 'data/style.conf' |
720 | --- data/style.conf 2011-01-16 21:57:51 +0000 |
721 | +++ data/style.conf 2011-06-04 21:27:03 +0000 |
722 | @@ -38,6 +38,9 @@ |
723 | foreground = blue |
724 | #underline = single |
725 | |
726 | +[Tag tag] |
727 | +foreground = #ce5c00 |
728 | + |
729 | |
730 | # For the various headings we scale the size relative to the font size. |
731 | # The color choosen is the dark green -or "Chameleon"- as defined in the |
732 | |
733 | === added file 'data/templates/_gnuplot.gnu' |
734 | --- data/templates/_gnuplot.gnu 1970-01-01 00:00:00 +0000 |
735 | +++ data/templates/_gnuplot.gnu 2011-06-04 21:27:03 +0000 |
736 | @@ -0,0 +1,5 @@ |
737 | +set term png |
738 | +set output '[% png_fname %]' |
739 | + |
740 | +[% gnuplot_script %] |
741 | + |
742 | |
743 | === modified file 'data/urls.list' |
744 | --- data/urls.list 2010-01-08 18:02:36 +0000 |
745 | +++ data/urls.list 2011-06-04 21:27:03 +0000 |
746 | @@ -21,7 +21,7 @@ |
747 | google http://www.google.com/search?q= |
748 | google.de http://www.google.de/search?q= |
749 | phpfn http://www.php.net/{NAME} |
750 | -go http://www.google.com/search?q={URL}&btnI=lucky |
751 | +go http://www.google.com/search?q={URL}&btnI=lucky |
752 | cpan http://search.cpan.org/search?query={URL}&mode=all |
753 | perldoc http://perldoc.perl.org/search.html?q= |
754 | |
755 | |
756 | === modified file 'debian/changelog' |
757 | --- debian/changelog 2011-02-19 16:27:44 +0000 |
758 | +++ debian/changelog 2011-06-04 21:27:03 +0000 |
759 | @@ -1,3 +1,15 @@ |
760 | +zim (0.52) maverick; urgency=low |
761 | + |
762 | + * Updated to release 0.52 |
763 | + |
764 | + -- Jaap Karssenberg <jaap.karssenberg@gmail.com> Thu, 28 Apr 2011 19:56:04 +0200 |
765 | + |
766 | +zim (0.51) maverick; urgency=low |
767 | + |
768 | + * Updated to release 0.51 |
769 | + |
770 | + -- Jaap Karssenberg <jaap.karssenberg@gmail.com> Tue, 19 Apr 2011 20:51:32 +0200 |
771 | + |
772 | zim (0.50) maverick; urgency=low |
773 | |
774 | * Updated to release 0.50 |
775 | |
776 | === modified file 'debian/control' |
777 | --- debian/control 2011-02-19 16:27:44 +0000 |
778 | +++ debian/control 2011-06-04 21:27:03 +0000 |
779 | @@ -3,7 +3,7 @@ |
780 | Priority: optional |
781 | Maintainer: Jaap Karssenberg <jaap.karssenberg@gmail.com> |
782 | Standards-Version: 3.9.1 |
783 | -Build-Depends: debhelper (>= 7.4.12), cdbs, python-support (>= 0.8), xdg-utils, python (>= 2.5), libgtk2.0-0 (>= 2.6), python-gtk2, python-xdg, python-simplejson | python (>= 2.6) |
784 | +Build-Depends: debhelper (>= 7.4.12), cdbs, python-support (>= 0.8), python-unittest2 | python (>= 2.7), xdg-utils, python (>= 2.5), libgtk2.0-0 (>= 2.6), python-gtk2, python-xdg, python-simplejson | python (>= 2.6) |
785 | |
786 | Package: zim |
787 | Architecture: all |
788 | |
789 | === modified file 'debian/pyversions' |
790 | --- debian/pyversions 2009-10-21 18:34:17 +0000 |
791 | +++ debian/pyversions 2011-06-04 21:27:03 +0000 |
792 | @@ -1,1 +1,1 @@ |
793 | -2.5,2.6 |
794 | +2.5,2.6,2.7 |
795 | |
796 | === modified file 'msgfmt.py' |
797 | --- msgfmt.py 2009-07-18 13:57:52 +0000 |
798 | +++ msgfmt.py 2011-06-04 21:27:03 +0000 |
799 | @@ -71,7 +71,6 @@ |
800 | offsets.append((len(ids), len(_id), len(strs), len(MESSAGES[_id]))) |
801 | ids += _id + '\0' |
802 | strs += MESSAGES[_id] + '\0' |
803 | - output = '' |
804 | # The header is 7 32-bit unsigned integers. We don't use hash tables, so |
805 | # the keys start right after the index tables. |
806 | # translated string. |
807 | |
808 | === modified file 'test.py' |
809 | --- test.py 2011-02-19 16:27:44 +0000 |
810 | +++ test.py 2011-06-04 21:27:03 +0000 |
811 | @@ -2,6 +2,10 @@ |
812 | |
813 | # -*- coding: utf-8 -*- |
814 | |
815 | +# This is a wrapper script to run tests using the unittest |
816 | +# framework. It setups the environment properly and defines some |
817 | +# commandline options for running tests. |
818 | +# |
819 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
820 | |
821 | import os |
822 | @@ -10,92 +14,8 @@ |
823 | import getopt |
824 | import logging |
825 | |
826 | -import unittest |
827 | -import time |
828 | -import types |
829 | - |
830 | import tests |
831 | - |
832 | -# TODO overload one of the unittest classes to test add file names |
833 | - |
834 | -pyfiles = [] |
835 | -for d, dirs, files in os.walk('zim'): |
836 | - pyfiles.extend([d+'/'+f for f in files if f.endswith('.py')]) |
837 | -pyfiles.sort() |
838 | - |
839 | -class FastTestLoader(unittest.TestLoader): |
840 | - '''Extension of TestLoader which ignores all classes which have an |
841 | - attribute 'slowTest' set to True. |
842 | - ''' |
843 | - |
844 | - def __init__(self, alltests=True): |
845 | - unittest.TestLoader.__init__(self) |
846 | - self.ignored = 0 |
847 | - self.skipped = 0 |
848 | - self.alltests = alltests |
849 | - |
850 | - def loadTestsFromModule(self, module): |
851 | - """Return a suite of all tests cases contained in the given module""" |
852 | - tests = [] |
853 | - for name in dir(module): |
854 | - obj = getattr(module, name) |
855 | - if (isinstance(obj, (type, types.ClassType)) and |
856 | - issubclass(obj, unittest.TestCase)): |
857 | - if not self.alltests and hasattr(obj, 'slowTest') and obj.slowTest: |
858 | - print 'Ignoring slow test:', obj.__name__ |
859 | - self.ignored += 1 |
860 | - elif hasattr(obj, 'skipTest') and obj.skipTest(): |
861 | - print 'Skipping test:', obj.__name__, '-', obj.skipTest() |
862 | - self.skipped += 1 |
863 | - else: |
864 | - tests.append(self.loadTestsFromTestCase(obj)) |
865 | - return self.suiteClass(tests) |
866 | - |
867 | - |
868 | -class MyTextTestRunner(unittest.TextTestRunner): |
869 | - '''Extionsion of TextTestRunner to report number of ignored tests in the |
870 | - proper place. |
871 | - ''' |
872 | - |
873 | - def __init__(self, verbosity, ignored, skipped): |
874 | - unittest.TextTestRunner.__init__(self, verbosity=verbosity) |
875 | - self.ignored = ignored |
876 | - self.skipped = skipped |
877 | - |
878 | - def run(self, test): |
879 | - "Run the given test case or test suite." |
880 | - result = self._makeResult() |
881 | - startTime = time.time() |
882 | - test(result) |
883 | - stopTime = time.time() |
884 | - timeTaken = stopTime - startTime |
885 | - result.printErrors() |
886 | - self.stream.writeln(result.separator2) |
887 | - run = result.testsRun |
888 | - self.stream.writeln("Ran %d test%s in %.3fs" % |
889 | - (run, run != 1 and "s" or "", timeTaken)) |
890 | - ignored = self.ignored |
891 | - if ignored > 0: |
892 | - self.stream.writeln("Ignored %d slow test%s" % |
893 | - (ignored, ignored != 1 and "s" or "")) |
894 | - skipped = self.skipped |
895 | - if skipped > 0: |
896 | - self.stream.writeln("Skipped %d test%s" % |
897 | - (skipped, skipped != 1 and "s" or "")) |
898 | - self.stream.writeln() |
899 | - if not result.wasSuccessful(): |
900 | - self.stream.write("FAILED (") |
901 | - failed, errored = map(len, (result.failures, result.errors)) |
902 | - if failed: |
903 | - self.stream.write("failures=%d" % failed) |
904 | - if errored: |
905 | - if failed: self.stream.write(", ") |
906 | - self.stream.write("errors=%d" % errored) |
907 | - self.stream.writeln(")") |
908 | - else: |
909 | - self.stream.writeln("OK") |
910 | - return result |
911 | - |
912 | +from tests import unittest |
913 | |
914 | |
915 | def main(argv=None): |
916 | @@ -105,9 +25,10 @@ |
917 | |
918 | # parse options |
919 | coverage = None |
920 | - alltests = True |
921 | + failfast = False |
922 | loglevel = logging.WARNING |
923 | - opts, args = getopt.gnu_getopt(argv[1:], 'hVD', ['help', 'coverage', 'fast', 'debug', 'verbose']) |
924 | + opts, args = getopt.gnu_getopt(argv[1:], |
925 | + 'hVD', ['help', 'coverage', 'fast', 'failfast', 'debug', 'verbose']) |
926 | for o, a in opts: |
927 | if o in ('-h', '--help'): |
928 | print '''\ |
929 | @@ -118,7 +39,8 @@ |
930 | |
931 | Options: |
932 | -h, --help print this text |
933 | - --fast skip a number of slower tests |
934 | + --fast skip a number of slower tests (assumes --failfast) |
935 | + --failfast stop after the first test that fails |
936 | --coverage report test coverage statistics |
937 | -V, --verbose run with verbose output from logging |
938 | -D, --debug run with debug output from logging |
939 | @@ -129,7 +51,7 @@ |
940 | import coverage as coverage_module |
941 | except ImportError: |
942 | print >>sys.stderr, '''\ |
943 | -Can not run test coverage without module coverage. |
944 | +Can not run test coverage without module 'coverage'. |
945 | On Ubuntu or Debian install package 'python-coverage'. |
946 | ''' |
947 | sys.exit(1) |
948 | @@ -139,7 +61,11 @@ |
949 | coverage.exclude('raise NotImplementedError') |
950 | coverage.start() |
951 | elif o == '--fast': |
952 | - alltests = False |
953 | + failfast = True |
954 | + tests.FAST_TEST = True |
955 | + # set before any test classes are loaded ! |
956 | + elif o == '--failfast': |
957 | + failfast = True |
958 | elif o in ('-V', '--verbose'): |
959 | loglevel = logging.INFO |
960 | elif o in ('-D', '--debug'): |
961 | @@ -150,28 +76,19 @@ |
962 | # Set logging handler |
963 | logging.basicConfig(level=loglevel, format='%(levelname)s: %(message)s') |
964 | |
965 | - # Set environment - so we can be sure we don't see |
966 | - # any data from a previous installed version |
967 | - tests.set_environ() |
968 | - |
969 | - # Collect the test cases |
970 | - suite = unittest.TestSuite() |
971 | - loader = FastTestLoader(alltests=alltests) |
972 | - |
973 | + # Build the test suite |
974 | + loader = unittest.TestLoader() |
975 | if args: |
976 | - modules = [ 'tests.'+name for name in args ] |
977 | + suite = unittest.TestSuite() |
978 | + for module in [ 'tests.'+name for name in args ]: |
979 | + test = loader.loadTestsFromName(module) |
980 | + suite.addTest(test) |
981 | else: |
982 | - suite.addTest(TestCompileAll()) |
983 | - suite.addTest(TestNotebookUpgrade()) |
984 | - modules = [ 'tests.'+name for name in tests.__all__ ] |
985 | - |
986 | - for name in modules: |
987 | - test = loader.loadTestsFromName(name) |
988 | - suite.addTest(test) |
989 | - |
990 | - # And run them |
991 | - MyTextTestRunner(verbosity=3, |
992 | - ignored=loader.ignored, skipped=loader.skipped).run(suite) |
993 | + suite = tests.load_tests(loader, None, None) |
994 | + |
995 | + # And run it |
996 | + unittest.installHandler() # Fancy handling for ^C during test |
997 | + unittest.TextTestRunner(verbosity=2, failfast=failfast).run(suite) |
998 | |
999 | # Check the modules were loaded from the right location |
1000 | # (so no testing based on modules from a previous installed version...) |
1001 | @@ -184,6 +101,7 @@ |
1002 | assert file.startswith(mylib), \ |
1003 | 'Module %s was loaded from %s' % (module, file) |
1004 | |
1005 | + # Create coverage output if asked to do so |
1006 | if coverage: |
1007 | coverage.stop() |
1008 | report_coverage(coverage) |
1009 | @@ -192,6 +110,7 @@ |
1010 | def report_coverage(coverage): |
1011 | print '' |
1012 | print 'Writing detailed coverage reports...' |
1013 | + pyfiles = list(tests.zim_pyfiles()) |
1014 | coverage.report(pyfiles, show_missing=False) |
1015 | |
1016 | # Detailed report in html |
1017 | @@ -307,25 +226,6 @@ |
1018 | print '\nDetailed coverage reports can be found in ./coverage/' |
1019 | |
1020 | |
1021 | -class TestCompileAll(unittest.TestCase): |
1022 | - |
1023 | - def runTest(self): |
1024 | - '''Test if all modules compile''' |
1025 | - for file in pyfiles: |
1026 | - module = file[:-3].replace('/', '.') |
1027 | - assert __import__(module) |
1028 | - |
1029 | - |
1030 | -class TestNotebookUpgrade(unittest.TestCase): |
1031 | - |
1032 | - def runTest(self): |
1033 | - '''Test if included notebooks are up to date''' |
1034 | - from zim.fs import Dir |
1035 | - from zim.notebook import get_notebook |
1036 | - for path in ('data/manual', 'HACKING'): |
1037 | - notebook = get_notebook(Dir(path)) |
1038 | - self.assertTrue(not notebook.needs_upgrade) |
1039 | - |
1040 | |
1041 | if __name__ == '__main__': |
1042 | main() |
1043 | |
1044 | === modified file 'tests/__init__.py' |
1045 | --- tests/__init__.py 2011-02-27 20:51:16 +0000 |
1046 | +++ tests/__init__.py 2011-06-04 21:27:03 +0000 |
1047 | @@ -7,14 +7,36 @@ |
1048 | import os |
1049 | import sys |
1050 | import shutil |
1051 | -import unittest |
1052 | import logging |
1053 | import gettext |
1054 | import xml.etree.cElementTree as etree |
1055 | - |
1056 | - |
1057 | +import types |
1058 | +import glob |
1059 | + |
1060 | +if sys.version_info < (2, 7, 0): |
1061 | + try: |
1062 | + import unittest2 as unittest |
1063 | + except ImportError: |
1064 | + print >>sys.stderr, '''\ |
1065 | +For python versions < 2.7 the 'unittest2' module is needed to run |
1066 | +the test suite. On Ubuntu or Debian install package 'python-unittest2'. |
1067 | +''' |
1068 | + sys.exit(1) |
1069 | +else: |
1070 | + import unittest |
1071 | + |
1072 | +from unittest import skip, skipIf, skipUnless |
1073 | + |
1074 | +__unittest = 1 # needed to get stack trace OK for class TestCase |
1075 | + |
1076 | +gettext.install('zim', unicode=True, names=('_', 'gettext', 'ngettext')) |
1077 | + |
1078 | +FAST_TEST = False #: determines whether we skip slow tests or not |
1079 | + |
1080 | + |
1081 | +# This list also determines the order in which tests will executed |
1082 | __all__ = [ |
1083 | - 'coding', 'translations', |
1084 | + 'package', 'translations', |
1085 | 'errors', 'parsing', 'fs', 'config', 'applications', 'async', |
1086 | 'formats', 'templates', 'inlineobjects', |
1087 | 'stores', 'index', 'notebook', |
1088 | @@ -22,17 +44,33 @@ |
1089 | 'export', 'www', 'search', |
1090 | 'widgets', 'gui', 'pageview', |
1091 | 'calendar', 'printtobrowser', 'versioncontrol', 'inlinecalculator', |
1092 | - 'tasklist', |
1093 | + 'tasklist', 'tags', |
1094 | 'equationeditor', 'diagrameditor', |
1095 | + 'daemon' # Note that running this test in another position can skrew up e.g. clipboard test |
1096 | ] |
1097 | |
1098 | -__unittest = 1 # needed to get stack trace OK for class TestCase |
1099 | - |
1100 | - |
1101 | -gettext.install('zim', unicode=True, names=('_', 'gettext', 'ngettext')) |
1102 | - |
1103 | - |
1104 | -def set_environ(): |
1105 | +# when a test is missing from the list that should be detected |
1106 | +for file in glob.glob(os.path.dirname(__file__) + '/*.py'): |
1107 | + name = os.path.basename(file)[:-3] |
1108 | + if name != '__init__' and not name in __all__: |
1109 | + raise AssertionError, 'Test missing in __all__: %s' % name |
1110 | + |
1111 | + |
1112 | +def load_tests(loader, tests, pattern): |
1113 | + '''Load all test cases and return a unittest.TestSuite object. |
1114 | + The parameters 'tests' and 'pattern' are ignored. |
1115 | + ''' |
1116 | + suite = unittest.TestSuite() |
1117 | + for name in ['tests.'+name for name in __all__ ]: |
1118 | + test = loader.loadTestsFromName(name) |
1119 | + suite.addTest(test) |
1120 | + return suite |
1121 | + |
1122 | + |
1123 | +def _setUpEnvironment(): |
1124 | + '''Method to be run once before test suite starts''' |
1125 | + # In fact to be loaded before loading some of the zim modules |
1126 | + # like zim.config and any that export constants from it |
1127 | tmpdir = './tests/tmp/' |
1128 | os.environ.update({ |
1129 | 'ZIM_TEST_RUNNING': 'True', |
1130 | @@ -55,75 +93,218 @@ |
1131 | os.makedirs(hicolor) |
1132 | |
1133 | |
1134 | -def create_tmp_dir(name): |
1135 | - '''Returns a path to a tmp dir for tests to store dump data. |
1136 | - The dir is removed and recreated empty every time this function |
1137 | - is called. |
1138 | +_setUpEnvironment() # just do this whenever we are loaded |
1139 | + |
1140 | + |
1141 | +_zim_pyfiles = [] |
1142 | + |
1143 | +def zim_pyfiles(): |
1144 | + '''Returns a list with file paths for all the zim python files''' |
1145 | + if not _zim_pyfiles: |
1146 | + for d, dirs, files in os.walk('zim'): |
1147 | + _zim_pyfiles.extend([d+'/'+f for f in files if f.endswith('.py')]) |
1148 | + _zim_pyfiles.sort() |
1149 | + for file in _zim_pyfiles: |
1150 | + yield file # shallow copy |
1151 | + |
1152 | + |
1153 | + |
1154 | +def gtk_process_events(*a): |
1155 | + '''Method to simulate a few iterations of the gtk main loop''' |
1156 | + import gtk |
1157 | + while gtk.events_pending(): |
1158 | + gtk.main_iteration(block=False) |
1159 | + return True # continue |
1160 | + |
1161 | + |
1162 | +def slowTest(obj): |
1163 | + '''Decorator for slow tests |
1164 | + |
1165 | + Tests wrapped with this decorator are ignored when you run |
1166 | + C{test.py --fast}. You can either wrap whole test classes:: |
1167 | + |
1168 | + @tests.slowTest |
1169 | + class MyTest(tests.TestCase): |
1170 | + ... |
1171 | + |
1172 | + or individual test functions:: |
1173 | + |
1174 | + class MyTest(tests.TestCase): |
1175 | + |
1176 | + @tests.slowTest |
1177 | + def testFoo(self): |
1178 | + ... |
1179 | + |
1180 | + def testBar(self): |
1181 | + ... |
1182 | ''' |
1183 | - dir = os.path.join('tests', 'tmp', name) |
1184 | - if os.name == 'nt': |
1185 | - dir = unicode(dir) |
1186 | + if FAST_TEST: |
1187 | + wrapper = skip('Slow test') |
1188 | + return wrapper(obj) |
1189 | else: |
1190 | - dir = dir.encode(sys.getfilesystemencoding()) |
1191 | - if os.path.exists(dir): |
1192 | - shutil.rmtree(dir) |
1193 | - assert not os.path.exists(dir) # make real sure |
1194 | - os.makedirs(dir) |
1195 | - assert os.path.exists(dir) # make real sure |
1196 | - return dir |
1197 | - |
1198 | - |
1199 | -_test_data_wiki = None |
1200 | - |
1201 | -def get_test_data(format): |
1202 | - global _test_data_wiki |
1203 | - assert format == 'wiki' # No other formats available for now |
1204 | - if _test_data_wiki is None: |
1205 | - _test_data_wiki = _get_test_data_wiki() |
1206 | - |
1207 | - for name, text in _test_data_wiki: |
1208 | - #~ print '>', name |
1209 | - yield name, text |
1210 | - |
1211 | - |
1212 | -def get_test_data_page(format, name): |
1213 | - global _test_data_wiki |
1214 | - assert format == 'wiki' # No other formats available for now |
1215 | - if not _test_data_wiki: |
1216 | - _test_data_wiki = _get_test_data_wiki() |
1217 | - |
1218 | - for n, text in _test_data_wiki: |
1219 | - if n == name: |
1220 | - return text |
1221 | - assert False, 'Could not find data for page: %s' % name |
1222 | - |
1223 | - |
1224 | -def _get_test_data_wiki(): |
1225 | - test_data = [] |
1226 | - tree = etree.ElementTree(file='tests/data/notebook-wiki.xml') |
1227 | - for node in tree.getiterator(tag='page'): |
1228 | - name = node.attrib['name'] |
1229 | - text = unicode(node.text.lstrip('\n')) |
1230 | - test_data.append((name, text)) |
1231 | - return tuple(test_data) |
1232 | - |
1233 | - |
1234 | -def get_test_notebook(format='wiki'): |
1235 | - '''Returns a notebook with a memory store and some test data''' |
1236 | - from zim.notebook import Notebook, Path |
1237 | - from zim.index import Index |
1238 | - notebook = Notebook(index=Index(dbfile=':memory:')) |
1239 | - store = notebook.add_store(Path(':'), 'memory') |
1240 | - manifest = [] |
1241 | - for name, text in get_test_data(format): |
1242 | - manifest.append(name) |
1243 | - store.set_node(Path(name), text) |
1244 | - notebook.testdata_manifest = expand_manifest(manifest) |
1245 | - notebook.index.update() |
1246 | - return notebook |
1247 | - |
1248 | - |
1249 | -def expand_manifest(names): |
1250 | + return obj |
1251 | + |
1252 | + |
1253 | +class TestCase(unittest.TestCase): |
1254 | + '''Base class for test cases''' |
1255 | + |
1256 | + def create_tmp_dir(self, name=None): |
1257 | + '''Returns a path to a tmp dir where tests can write data. |
1258 | + The dir is removed and recreated empty every time this function |
1259 | + is called with the same name from the same class. |
1260 | + ''' |
1261 | + path = self._get_tmp_name(name) |
1262 | + if os.path.exists(path): |
1263 | + shutil.rmtree(path) |
1264 | + assert not os.path.exists(path) # make real sure |
1265 | + os.makedirs(path) |
1266 | + assert os.path.exists(path) # make real sure |
1267 | + return path |
1268 | + |
1269 | + def get_tmp_name(self, name=None): |
1270 | + '''Returns the same path as L{create_tmp_dir()} but without |
1271 | + touching it. This method will raise an exception when a file |
1272 | + or dir exists of the same name. |
1273 | + ''' |
1274 | + path = self._get_tmp_name(name) |
1275 | + assert not os.path.exists(path), 'This path should not exist: %s' % path |
1276 | + return path |
1277 | + |
1278 | + def _get_tmp_name(self, name): |
1279 | + if name: |
1280 | + assert not os.path.sep in name, 'Don\'t use this method to get sub folders or files' |
1281 | + name = self.__class__.__name__ + '_' + name |
1282 | + else: |
1283 | + name = self.__class__.__name__ |
1284 | + |
1285 | + dir = os.path.dirname(__file__) |
1286 | + path = os.path.join(dir, 'tmp', name) |
1287 | + if os.name == 'nt': |
1288 | + path = unicode(path) |
1289 | + else: |
1290 | + path = path.encode(sys.getfilesystemencoding()) |
1291 | + |
1292 | + return path |
1293 | + |
1294 | + |
1295 | +class LoggingFilter(object): |
1296 | + '''Base class for logging filters that can be used as a context |
1297 | + using the "with" keyword. To subclass it you only need to set the |
1298 | + logger to be used and (the begin of) the message to filter. |
1299 | + ''' |
1300 | + |
1301 | + logger = None |
1302 | + message = None |
1303 | + |
1304 | + def __init__(self, logger=None, message=None): |
1305 | + if logger: self.logger = logger |
1306 | + if message: self.message = message |
1307 | + |
1308 | + self.loggerobj = logging.getLogger(self.logger) |
1309 | + |
1310 | + def __enter__(self): |
1311 | + self.loggerobj.addFilter(self) |
1312 | + |
1313 | + def __exit__(self, *a): |
1314 | + self.loggerobj.removeFilter(self) |
1315 | + |
1316 | + def filter(self, record): |
1317 | + return not record.getMessage().startswith(self.message) |
1318 | + |
1319 | + |
1320 | +class DialogContext(object): |
1321 | + '''Context manager to catch dialogs being opened |
1322 | + |
1323 | + Inteded to be used like this:: |
1324 | + |
1325 | + def myCustomTest(dialog): |
1326 | + self.assertTrue(isinstance(dialog, CustomDialogClass)) |
1327 | + # ... |
1328 | + dialog.assert_response_ok() |
1329 | + |
1330 | + with DialogContext( |
1331 | + myCustomTest, |
1332 | + SomeOtherDialogClass |
1333 | + ): |
1334 | + gui.show_dialogs() |
1335 | + |
1336 | + In this example the first dialog that is run by C{gui.show_dialogs()} |
1337 | + is checked by the function C{myCustomTest()} while the second dialog |
1338 | + just needs to be of class C{SomeOtherDialogClass} and will then |
1339 | + be closed with C{assert_response_ok()} by the context manager. |
1340 | + |
1341 | + This context only works for dialogs derived from zim's Dialog class |
1342 | + as it uses a special hook in L{zim.gui.widgets}. |
1343 | + ''' |
1344 | + |
1345 | + def __init__(self, *definitions): |
1346 | + '''Constructor |
1347 | + @param definitions: list of either classes or methods |
1348 | + ''' |
1349 | + self.stack = list(definitions) |
1350 | + self.old_test_mode = None |
1351 | + |
1352 | + def __enter__(self): |
1353 | + import zim.gui.widgets |
1354 | + self.old_test_mode = zim.gui.widgets.TEST_MODE |
1355 | + self.old_callback = zim.gui.widgets.TEST_MODE_RUN_CB |
1356 | + zim.gui.widgets.TEST_MODE = True |
1357 | + zim.gui.widgets.TEST_MODE_RUN_CB = self._callback |
1358 | + |
1359 | + def _callback(self, dialog): |
1360 | + #~ print '>>>', dialog |
1361 | + if not self.stack: |
1362 | + raise AssertionError, 'Unexpected dialog run: %s' % dialog |
1363 | + |
1364 | + handler = self.stack.pop(0) |
1365 | + |
1366 | + if isinstance(handler, (type, types.ClassType)): # is a class |
1367 | + if not isinstance(dialog, handler): |
1368 | + raise AssertionError, 'Expected dialog of class %s, but got %s instead' % (handler, dialog.__class__) |
1369 | + dialog.assert_response_ok() |
1370 | + else: # assume a function |
1371 | + handler(dialog) |
1372 | + |
1373 | + def __exit__(self, *error): |
1374 | + #~ print 'ERROR', error |
1375 | + import zim.gui.widgets |
1376 | + zim.gui.widgets.TEST_MODE = self.old_test_mode |
1377 | + zim.gui.widgets.TEST_MODE_RUN_CB = self.old_callback |
1378 | + return False # Raise any errors again outside context |
1379 | + |
1380 | + |
1381 | +class TestData(object): |
1382 | + '''Wrapper for a set of test data in tests/data''' |
1383 | + |
1384 | + def __init__(self, format): |
1385 | + assert format == 'wiki', 'TODO: add other formats' |
1386 | + tree = etree.ElementTree(file='tests/data/notebook-wiki.xml') |
1387 | + |
1388 | + test_data = [] |
1389 | + for node in tree.getiterator(tag='page'): |
1390 | + name = node.attrib['name'] |
1391 | + text = unicode(node.text.lstrip('\n')) |
1392 | + test_data.append((name, text)) |
1393 | + |
1394 | + self._test_data = tuple(test_data) |
1395 | + |
1396 | + def __iter__(self): |
1397 | + '''Yield the test data as 2 tuple (pagename, text)''' |
1398 | + for name, text in self._test_data: |
1399 | + yield name, text # shallow copy |
1400 | + |
1401 | + def get(self, pagename): |
1402 | + '''Return text for a specific pagename''' |
1403 | + for n, text in self._test_data: |
1404 | + if n == pagename: |
1405 | + return text |
1406 | + assert False, 'Could not find data for page: %s' % pagename |
1407 | + |
1408 | + |
1409 | +WikiTestData = TestData('wiki') #: singleton to be used by various tests |
1410 | + |
1411 | + |
1412 | +def _expand_manifest(names): |
1413 | '''Build a set of all pages names and all namespaces that need to |
1414 | exist to host those page names. |
1415 | ''' |
1416 | @@ -137,96 +318,63 @@ |
1417 | return manifest |
1418 | |
1419 | |
1420 | -def get_test_page(name='Foo'): |
1421 | - '''FIXME''' |
1422 | +def new_notebook(fakedir=None): |
1423 | + '''Returns a new Notebook object with all data in memory |
1424 | + |
1425 | + Uses data from L{WikiTestData} |
1426 | + |
1427 | + @param fakedir: optional parameter to set the 'dir' attribute for |
1428 | + the notebook and the main store which allows you to resolve file |
1429 | + paths etc. It will not automatically touch the dir |
1430 | + (hence it being 'fake'). |
1431 | + ''' |
1432 | + from zim.fs import Dir |
1433 | from zim.notebook import Notebook, Path |
1434 | - notebook = Notebook() |
1435 | - notebook.add_store(Path(':'), 'memory') |
1436 | - return notebook, notebook.get_page(Path(name)) |
1437 | - |
1438 | - |
1439 | -def print_index(index): |
1440 | - print '==== INDEX ====' |
1441 | - for page in index.walk(): |
1442 | - print page.name, page.hascontent, page.haschildren |
1443 | - for link in index.list_links(page): |
1444 | - print '\t->', link.href.name |
1445 | - print '===============' |
1446 | - |
1447 | - |
1448 | - |
1449 | -class TestCase(unittest.TestCase): |
1450 | - '''Base class for test cases''' |
1451 | - |
1452 | - def run(self, *args): |
1453 | - unittest.TestCase.run(self, *args) |
1454 | - |
1455 | - def assertEqualDiff(self, first, second, msg=None): |
1456 | - '''Fail if the two strings are unequal as determined by |
1457 | - the '==' operator. On failure shows a diff of both strings. |
1458 | - Alternatively the arguments can be lists of lines. |
1459 | - ''' |
1460 | - if msg is None: |
1461 | - msg = u'Strings differ:' |
1462 | - else: |
1463 | - msg = unicode(msg) |
1464 | - |
1465 | - if not type(first) == type(second): |
1466 | - types = type(first), type(second) |
1467 | - msg += ' types differ, %s and %s' % types |
1468 | - elif not first: |
1469 | - msg += ' first text is empty' |
1470 | - elif not second: |
1471 | - msg += ' second text is empty' |
1472 | - elif not first == second: |
1473 | - from difflib import Differ |
1474 | - if isinstance(first, basestring): |
1475 | - first = first.splitlines(True) |
1476 | - if isinstance(second, basestring): |
1477 | - second = second.splitlines(True) |
1478 | - diff = Differ().compare(second, first) |
1479 | - # switching first and second, because usually second |
1480 | - # is the reference we are testing against |
1481 | - msg += '\n' + ''.join(diff) |
1482 | - else: |
1483 | - return |
1484 | - |
1485 | - raise self.failureException, msg.encode('utf-8') |
1486 | - |
1487 | - def assertEqualDiffData(self, first, second, msg=None): |
1488 | - '''Like assertEqualDiff(), but handles sets and other |
1489 | - data types that can be cast to lists. |
1490 | - ''' |
1491 | - if msg is None: |
1492 | - msg = u'Values differ:' |
1493 | - else: |
1494 | - msg = unicode(msg) |
1495 | - |
1496 | - if not type(first) == type(second): |
1497 | - types = type(first), type(second) |
1498 | - msg += ' types differ, %s and %s' % types |
1499 | - elif first is None: |
1500 | - msg += ' first item is "None"' |
1501 | - elif second is None: |
1502 | - msg += ' second item is "None"' |
1503 | - elif not first == second: |
1504 | - from difflib import Differ |
1505 | - if isinstance(first, set): |
1506 | - first = list(first) |
1507 | - second = list(second) |
1508 | - first.sort() |
1509 | - second.sort() |
1510 | - else: |
1511 | - first = list(first) |
1512 | - second = list(second) |
1513 | - diff = Differ().compare(second, first) |
1514 | - # switching first and second, because usually second |
1515 | - # is the reference we are testing against |
1516 | - msg += '\n' + '\n'.join(diff) |
1517 | - else: |
1518 | - return |
1519 | - |
1520 | - raise self.failureException, msg.encode('utf-8') |
1521 | + from zim.index import Index |
1522 | + |
1523 | + notebook = Notebook(index=Index(dbfile=':memory:')) |
1524 | + store = notebook.add_store(Path(':'), 'memory') |
1525 | + manifest = [] |
1526 | + for name, text in WikiTestData: |
1527 | + manifest.append(name) |
1528 | + store.set_node(Path(name), text) |
1529 | + notebook.testdata_manifest = _expand_manifest(manifest) |
1530 | + notebook.index.update() |
1531 | + |
1532 | + if fakedir: |
1533 | + dir = Dir(fakedir) |
1534 | + notebook.dir = dir |
1535 | + store.dir = dir |
1536 | + |
1537 | + return notebook |
1538 | + |
1539 | + |
1540 | +def new_files_notebook(dir): |
1541 | + '''Returns a new Notebook object with a file store |
1542 | + |
1543 | + Uses data from L{WikiTestData} |
1544 | + |
1545 | + @param path: a folder path, e.g. created by L{TestCase.create_tmp_dir()} |
1546 | + ''' |
1547 | + from zim.fs import Dir |
1548 | + from zim.notebook import init_notebook, Notebook, Path |
1549 | + from zim.index import Index |
1550 | + |
1551 | + dir = Dir(dir) |
1552 | + init_notebook(dir) |
1553 | + notebook = Notebook(dir=dir) |
1554 | + store = notebook.get_store(':') |
1555 | + manifest = [] |
1556 | + for name, text in WikiTestData: |
1557 | + manifest.append(name) |
1558 | + page = store.get_page(Path(name)) |
1559 | + page.parse('wiki', text) |
1560 | + store.store_page(page) |
1561 | + notebook.testdata_manifest = _expand_manifest(manifest) |
1562 | + notebook.index.update() |
1563 | + |
1564 | + return notebook |
1565 | + |
1566 | |
1567 | |
1568 | class MockObject(object): |
1569 | @@ -260,28 +408,3 @@ |
1570 | |
1571 | setattr(self, name, my_mock_method) |
1572 | return my_mock_method |
1573 | - |
1574 | - |
1575 | -class LoggingFilter(object): |
1576 | - '''Base class for logging filters that can be used as a context |
1577 | - using the "with" keyword. To subclass it you only need to set the |
1578 | - logger to be used and (the begin of) the message to filter. |
1579 | - ''' |
1580 | - |
1581 | - logger = None |
1582 | - message = None |
1583 | - |
1584 | - def __init__(self, logger=None, message=None): |
1585 | - if logger: self.logger = logger |
1586 | - if message: self.message = message |
1587 | - |
1588 | - self.loggerobj = logging.getLogger(self.logger) |
1589 | - |
1590 | - def __enter__(self): |
1591 | - self.loggerobj.addFilter(self) |
1592 | - |
1593 | - def __exit__(self, *a): |
1594 | - self.loggerobj.removeFilter(self) |
1595 | - |
1596 | - def filter(self, record): |
1597 | - return not record.getMessage().startswith(self.message) |
1598 | |
1599 | === modified file 'tests/applications.py' |
1600 | --- tests/applications.py 2011-02-19 16:27:44 +0000 |
1601 | +++ tests/applications.py 2011-06-04 21:27:03 +0000 |
1602 | @@ -1,10 +1,8 @@ |
1603 | - |
1604 | # -*- coding: utf-8 -*- |
1605 | |
1606 | # Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
1607 | |
1608 | import tests |
1609 | -from tests import TestCase, create_tmp_dir |
1610 | |
1611 | import os |
1612 | import gtk |
1613 | @@ -22,7 +20,7 @@ |
1614 | return tuple(l) |
1615 | |
1616 | |
1617 | -class TestApplications(TestCase): |
1618 | +class TestApplications(tests.TestCase): |
1619 | |
1620 | def testParseExec(self): |
1621 | '''Test parsing of .desktop Exec strings''' |
1622 | @@ -76,7 +74,8 @@ |
1623 | self.assertEqual(result, wanted) |
1624 | |
1625 | |
1626 | -class TestCustomTools(TestCase): |
1627 | +@tests.slowTest |
1628 | +class TestCustomTools(tests.TestCase): |
1629 | |
1630 | def testManager(self): |
1631 | '''Test CustomToolManager API''' |
1632 | @@ -166,15 +165,14 @@ |
1633 | # %t for selected text or word under cursor |
1634 | # %T for selected text or word under cursor with wiki format |
1635 | |
1636 | - notebook = tests.get_test_notebook() |
1637 | + path = self.get_tmp_name() |
1638 | + notebook = tests.new_notebook(fakedir=path) |
1639 | page = notebook.get_page(Path('Test:Foo')) |
1640 | pageview = StubPageView() |
1641 | args = (notebook, page, pageview) |
1642 | |
1643 | tmpfile = TmpFile('tmp-page-source.txt').path |
1644 | - dir = Dir(tests.create_tmp_dir('applications_TestCustomTools')) |
1645 | - notebook.dir = dir # fake file store |
1646 | - notebook._stores[''].dir = dir # fake file store |
1647 | + dir = notebook.dir |
1648 | |
1649 | tool = CustomToolDict() |
1650 | tool.update( { |
1651 | |
1652 | === modified file 'tests/async.py' |
1653 | --- tests/async.py 2011-02-19 16:27:44 +0000 |
1654 | +++ tests/async.py 2011-06-04 21:27:03 +0000 |
1655 | @@ -9,6 +9,7 @@ |
1656 | |
1657 | import tests |
1658 | |
1659 | +import time |
1660 | |
1661 | from zim.async import * |
1662 | from zim.fs import File |
1663 | @@ -31,10 +32,11 @@ |
1664 | |
1665 | self.assertEqual(value, 'foo bar') |
1666 | |
1667 | + @tests.slowTest |
1668 | def testFS(self): |
1669 | '''Test async FS operations''' |
1670 | |
1671 | - self.path = tests.create_tmp_dir('async_testFS')+'/file.txt' |
1672 | + self.path = self.create_tmp_dir('testFS')+'/file.txt' |
1673 | |
1674 | file = File(self.path) |
1675 | |
1676 | @@ -45,3 +47,31 @@ |
1677 | op2.wait() |
1678 | |
1679 | self.assertEqual(file.read(), 'foo bar 2\n') |
1680 | + |
1681 | + |
1682 | +class Counter(object): |
1683 | + |
1684 | + def __init__(self): |
1685 | + self.i = 0 |
1686 | + |
1687 | + def count(self): |
1688 | + self.i += 1 |
1689 | + |
1690 | + |
1691 | +@tests.slowTest |
1692 | +class TestDelayedCallback(tests.TestCase): |
1693 | + |
1694 | + def runTest(self): |
1695 | + counter = Counter() |
1696 | + |
1697 | + callback = DelayedCallback(500, lambda o: counter.count()) |
1698 | + for i in range(3): |
1699 | + callback('foo') |
1700 | + |
1701 | + for i in range(10): |
1702 | + time.sleep(1) |
1703 | + tests.gtk_process_events() |
1704 | + if callback.timer_id is None: |
1705 | + break |
1706 | + |
1707 | + self.assertEqual(counter.i, 1) |
1708 | |
1709 | === modified file 'tests/calendar.py' |
1710 | --- tests/calendar.py 2011-02-19 16:27:44 +0000 |
1711 | +++ tests/calendar.py 2011-06-04 21:27:03 +0000 |
1712 | @@ -1,10 +1,9 @@ |
1713 | - |
1714 | # -*- coding: utf-8 -*- |
1715 | |
1716 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
1717 | |
1718 | import tests |
1719 | -from tests import TestCase |
1720 | + |
1721 | |
1722 | from datetime import date as dateclass |
1723 | |
1724 | @@ -13,9 +12,9 @@ |
1725 | from zim.config import ConfigDict |
1726 | |
1727 | |
1728 | -class TestCalendarPlugin(TestCase): |
1729 | +@tests.slowTest |
1730 | +class TestCalendarPlugin(tests.TestCase): |
1731 | |
1732 | - slowTest = True |
1733 | |
1734 | def runTest(self): |
1735 | 'Test Calendar plugin' |
1736 | @@ -38,11 +37,11 @@ |
1737 | ui_type = 'stub' |
1738 | |
1739 | def __init__(self): |
1740 | - self.notebook = tests.get_test_notebook() |
1741 | + self.notebook = tests.new_notebook() |
1742 | self.page = self.notebook.get_page(Path('Test:foo')) |
1743 | self.preferences = ConfigDict() |
1744 | self.uistate = ConfigDict() |
1745 | - |
1746 | + |
1747 | def connect(*a): pass |
1748 | |
1749 | def connect_after(*a): pass |
1750 | |
1751 | === modified file 'tests/config.py' |
1752 | --- tests/config.py 2011-02-19 16:27:44 +0000 |
1753 | +++ tests/config.py 2011-06-04 21:27:03 +0000 |
1754 | @@ -21,6 +21,7 @@ |
1755 | message = 'Invalid config value' |
1756 | |
1757 | |
1758 | + |
1759 | class TestDirsTestSetup(TestCase): |
1760 | |
1761 | def runTest(self): |
1762 | @@ -40,16 +41,22 @@ |
1763 | class TestDirsDefault(TestCase): |
1764 | |
1765 | def setUp(self): |
1766 | + old_environ = {} |
1767 | for k in ( |
1768 | 'XDG_DATA_HOME', 'XDG_DATA_DIRS', |
1769 | 'XDG_CONFIG_HOME', 'XDG_CONFIG_DIRS', 'XDG_CACHE_HOME' |
1770 | ): |
1771 | - if k in os.environ: del os.environ[k] |
1772 | - |
1773 | - zim.config._set_basedirs() # refresh |
1774 | - |
1775 | - def tearDown(self): |
1776 | - tests.set_environ() # re-set the environment |
1777 | + if k in os.environ: |
1778 | + old_environ[k] = os.environ[k] |
1779 | + del os.environ[k] |
1780 | + |
1781 | + def restore_environ(): |
1782 | + for k, v in old_environ.items(): |
1783 | + os.environ[k] = v |
1784 | + zim.config._set_basedirs() # refresh |
1785 | + |
1786 | + self.addCleanup(restore_environ) |
1787 | + |
1788 | zim.config._set_basedirs() # refresh |
1789 | |
1790 | def testValid(self): |
1791 | @@ -91,14 +98,25 @@ |
1792 | class TestDirsEnvironment(TestDirsDefault): |
1793 | |
1794 | def setUp(self): |
1795 | - os.environ.update( ( |
1796 | - ('XDG_DATA_HOME', '/foo/data/home'), |
1797 | - ('XDG_DATA_DIRS', '/foo/data/dir1:/foo/data/dir2'), |
1798 | - ('XDG_CONFIG_HOME', '/foo/config/home'), |
1799 | - ('XDG_CONFIG_DIRS', '/foo/config/dir1:/foo/config/dir2'), |
1800 | - ('XDG_CACHE_HOME', '/foo/cache') |
1801 | - ) ) |
1802 | - |
1803 | + my_environ = { |
1804 | + 'XDG_DATA_HOME': '/foo/data/home', |
1805 | + 'XDG_DATA_DIRS': '/foo/data/dir1:/foo/data/dir2', |
1806 | + 'XDG_CONFIG_HOME': '/foo/config/home', |
1807 | + 'XDG_CONFIG_DIRS': '/foo/config/dir1:/foo/config/dir2', |
1808 | + 'XDG_CACHE_HOME': '/foo/cache', |
1809 | + } |
1810 | + |
1811 | + old_environ = dict((name, os.environ.get(name)) for name in my_environ) |
1812 | + |
1813 | + def restore_environ(): |
1814 | + for k, v in old_environ.items(): |
1815 | + if v: |
1816 | + os.environ[k] = v |
1817 | + zim.config._set_basedirs() # refresh |
1818 | + |
1819 | + self.addCleanup(restore_environ) |
1820 | + |
1821 | + os.environ.update(my_environ) |
1822 | zim.config._set_basedirs() # refresh |
1823 | |
1824 | def testCorrect(self): |
1825 | @@ -147,7 +165,7 @@ |
1826 | none=None |
1827 | |
1828 | ''' |
1829 | - self.assertEqualDiff(file.read(), text) |
1830 | + self.assertEqual(file.read(), text) |
1831 | |
1832 | del conf |
1833 | conf = ConfigDictFile(file) |
1834 | @@ -336,7 +354,7 @@ |
1835 | headers = HeadersDict(text) |
1836 | self.assertEqual(headers['Foobar'], '123') |
1837 | self.assertEqual(headers['More-Lines'], 'test\n1234\ntest') |
1838 | - self.assertEqualDiff(headers.dump(), text.splitlines(True)) |
1839 | + self.assertEqual(headers.dump(), text.splitlines(True)) |
1840 | |
1841 | moretext='''\ |
1842 | Foobar: 123 |
1843 | @@ -351,8 +369,8 @@ |
1844 | lines = moretext.splitlines(True) |
1845 | headers = HeadersDict() |
1846 | headers.read(lines) |
1847 | - self.assertEqualDiff(headers.dump(), text.splitlines(True)) |
1848 | - self.assertEqualDiff(lines, ['test 123\n', 'test 456\n']) |
1849 | + self.assertEqual(headers.dump(), text.splitlines(True)) |
1850 | + self.assertEqual(lines, ['test 123\n', 'test 456\n']) |
1851 | |
1852 | # error tolerance and case insensitivity |
1853 | text = '''\ |
1854 | @@ -420,4 +438,3 @@ |
1855 | self.assertEqual(dict[Path('foo:bar:baz')]['key1'], 'foo') |
1856 | dict['']['key2'] = 'FOO' |
1857 | self.assertEqual(dict[Path('foo:bar:baz')]['key2'], 'FOO') |
1858 | - |
1859 | |
1860 | === modified file 'tests/daemon.py' |
1861 | --- tests/daemon.py 2011-02-19 16:27:44 +0000 |
1862 | +++ tests/daemon.py 2011-06-04 21:27:03 +0000 |
1863 | @@ -4,7 +4,6 @@ |
1864 | # Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
1865 | |
1866 | import tests |
1867 | -from tests import TestCase |
1868 | |
1869 | import os |
1870 | import time |
1871 | @@ -27,21 +26,13 @@ |
1872 | assert file.exists() == exists, 'File did not (dis-)appear' |
1873 | |
1874 | |
1875 | -class TestDaemon(TestCase): |
1876 | - |
1877 | - slowTest = True |
1878 | - |
1879 | - @classmethod |
1880 | - def skipTest(klass): |
1881 | - if os.name == 'nt': |
1882 | - return 'Daemon not supported on Windows' |
1883 | - else: |
1884 | - return False |
1885 | - |
1886 | +@tests.slowTest |
1887 | +@tests.skipIf(os.name == 'nt', 'Daemon not supported on Windows') |
1888 | +class TestDaemon(tests.TestCase): |
1889 | |
1890 | def runTest(self): |
1891 | '''Test GUI daemon interaction''' |
1892 | - dir = Dir(tests.create_tmp_dir('daemon')) |
1893 | + dir = Dir(self.create_tmp_dir()) |
1894 | socket = dir.file('test-socket') |
1895 | pidfile = dir.file('daemon.pid') |
1896 | |
1897 | |
1898 | === modified file 'tests/data/notebook-wiki.xml' |
1899 | --- tests/data/notebook-wiki.xml 2010-09-12 21:33:23 +0000 |
1900 | +++ tests/data/notebook-wiki.xml 2011-06-04 21:27:03 +0000 |
1901 | @@ -1,6 +1,9 @@ |
1902 | <?xml version="1.0" encoding="utf-8"?> |
1903 | <!-- this file is NOT in store.xml format --> |
1904 | <pagelist> |
1905 | +<page name="TODOList"> |
1906 | +TEst 123 |
1907 | +</page> |
1908 | <page name="TODOList:foo"> |
1909 | TODO: fix 1 !!! |
1910 | |
1911 | @@ -17,6 +20,15 @@ |
1912 | |
1913 | [[Test:Foo:BAR]] |
1914 | </page> |
1915 | +<page name='TrashMe'> |
1916 | +Trash me! |
1917 | +</page> |
1918 | +<page name='TrashMe:sub page 1'> |
1919 | +Trash me! |
1920 | +</page> |
1921 | +<page name='TrashMe:sub page 2'> |
1922 | +Trash me! |
1923 | +</page> |
1924 | <page name="Test:wiki"> |
1925 | Content-Type: text/x-zim-wiki |
1926 | Wiki-Format: zim 0.26 |
1927 | @@ -139,6 +151,31 @@ |
1928 | |
1929 | •• Search Me •• |
1930 | </page> |
1931 | +<page name="Test:tags"> |
1932 | += Tags = |
1933 | + |
1934 | +This page contains @tags in all kind of@places like the |
1935 | +@beginning of a line or its @end |
1936 | +but also after |
1937 | + |
1938 | + @tabs i.e. within @verbatim blocks |
1939 | + |
1940 | +within [[foo:bar|Link @captions]] as well as |
1941 | +* @enumerations |
1942 | + |
1943 | +Not to forget within |
1944 | + |
1945 | +== @Headings == |
1946 | + |
1947 | +and |
1948 | + |
1949 | +=== Their last @word === |
1950 | + |
1951 | +And with a different @encoding |
1952 | + |
1953 | +It also tests which weird @s!gns (sees only "s") and @num6ers @wit#in (aka |
1954 | +"wit") tags and tries hard to @cr@sh ("cr") the parser. |
1955 | +</page> |
1956 | <page name="Test:Foo Bar:Dus Ja Hmm"> |
1957 | Testing with whitespace in page name |
1958 | </page> |
1959 | @@ -169,6 +206,7 @@ |
1960 | IMAGE: {{../my-image.png?width=600|Foo Bar}} |
1961 | LINKS: [[:foo:bar]] [[./file.png]] file:///etc/passwd |
1962 | LINKS: [[Foo]][[Bar]] |
1963 | +TAGS: @foo @bar |
1964 | |
1965 | Some indented |
1966 | paragraphs go here ... |
1967 | |
1968 | === modified file 'tests/diagrameditor.py' |
1969 | --- tests/diagrameditor.py 2011-02-19 16:27:44 +0000 |
1970 | +++ tests/diagrameditor.py 2011-06-04 21:27:03 +0000 |
1971 | @@ -3,20 +3,13 @@ |
1972 | # Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
1973 | |
1974 | import tests |
1975 | -from tests import TestCase |
1976 | |
1977 | from zim.plugins.diagrameditor import * |
1978 | |
1979 | -class TestDiagramEditor(TestCase): |
1980 | - |
1981 | - slowTest = True |
1982 | - |
1983 | - @classmethod |
1984 | - def skipTest(klass): |
1985 | - if not InsertDiagramPlugin.check_dependencies_ok(): |
1986 | - return 'Missing dependencies' |
1987 | - else: |
1988 | - return False |
1989 | + |
1990 | +@tests.slowTest |
1991 | +@tests.skipUnless(InsertDiagramPlugin.check_dependencies_ok(), 'Missing dependencies') |
1992 | +class TestDiagramEditor(tests.TestCase): |
1993 | |
1994 | def runTest(self): |
1995 | 'Test Diagram Editor plugin' |
1996 | |
1997 | === modified file 'tests/equationeditor.py' |
1998 | --- tests/equationeditor.py 2011-02-19 16:27:44 +0000 |
1999 | +++ tests/equationeditor.py 2011-06-04 21:27:03 +0000 |
2000 | @@ -3,20 +3,13 @@ |
2001 | # Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
2002 | |
2003 | import tests |
2004 | -from tests import TestCase |
2005 | |
2006 | from zim.plugins.equationeditor import * |
2007 | |
2008 | -class TestEquationEditor(TestCase): |
2009 | - |
2010 | - slowTest = True |
2011 | - |
2012 | - @classmethod |
2013 | - def skipTest(klass): |
2014 | - if not InsertEquationPlugin.check_dependencies_ok(): |
2015 | - return 'Missing dependencies' |
2016 | - else: |
2017 | - return False |
2018 | + |
2019 | +@tests.slowTest |
2020 | +@tests.skipUnless(InsertEquationPlugin.check_dependencies_ok(), 'Missing dependencies') |
2021 | +class TestEquationEditor(tests.TestCase): |
2022 | |
2023 | def runTest(self): |
2024 | 'Test Equation Editor plugin' |
2025 | |
2026 | === modified file 'tests/export.py' |
2027 | --- tests/export.py 2011-02-19 16:27:44 +0000 |
2028 | +++ tests/export.py 2011-06-04 21:27:03 +0000 |
2029 | @@ -2,7 +2,8 @@ |
2030 | |
2031 | # Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
2032 | |
2033 | -from tests import TestCase, MockObject, create_tmp_dir, get_test_notebook, get_test_data |
2034 | +import tests |
2035 | + |
2036 | |
2037 | from subprocess import check_call |
2038 | |
2039 | @@ -12,38 +13,35 @@ |
2040 | |
2041 | # TODO add check that attachments are copied correctly |
2042 | |
2043 | -class TestLinker(TestCase): |
2044 | +class TestLinker(tests.TestCase): |
2045 | |
2046 | def runTest(self): |
2047 | '''Test proper linking of files in export''' |
2048 | - notebook = get_test_notebook() |
2049 | - notebook.get_store(Path(':')).dir = Dir('/source/dir/') # fake source dir |
2050 | + notebook = tests.new_notebook(fakedir='/source/dir/') |
2051 | |
2052 | linker = StaticLinker('html', notebook) |
2053 | linker.set_usebase(True) # normally set by html format module |
2054 | linker.set_path(Path('foo:bar')) # normally set by exporter |
2055 | linker.set_base(Dir('/source/dir/foo')) # normally set by exporter |
2056 | |
2057 | - self.assertEqual(linker.page('+dus'), './bar/dus.html') |
2058 | - self.assertEqual(linker.page('dus'), './dus.html') |
2059 | - self.assertEqual(linker.file('./dus.pdf'), './bar/dus.pdf') |
2060 | - self.assertEqual(linker.file('../dus.pdf'), './dus.pdf') |
2061 | - self.assertEqual(linker.file('../../dus.pdf'), '../dus.pdf') |
2062 | - |
2063 | - |
2064 | -class TestExport(TestCase): |
2065 | - |
2066 | - slowTest = True |
2067 | + self.assertEqual(linker.link_page('+dus'), './bar/dus.html') |
2068 | + self.assertEqual(linker.link_page('dus'), './dus.html') |
2069 | + self.assertEqual(linker.link_file('./dus.pdf'), './bar/dus.pdf') |
2070 | + self.assertEqual(linker.link_file('../dus.pdf'), './dus.pdf') |
2071 | + self.assertEqual(linker.link_file('../../dus.pdf'), '../dus.pdf') |
2072 | + |
2073 | + |
2074 | +@tests.slowTest |
2075 | +class TestExport(tests.TestCase): |
2076 | |
2077 | options = {'format': 'html', 'template': 'Default'} |
2078 | |
2079 | def setUp(self): |
2080 | - self.dir = Dir(create_tmp_dir('export_ExportedFiles')) |
2081 | + self.dir = Dir(self.create_tmp_dir('exported_files')) |
2082 | |
2083 | def export(self): |
2084 | - notebook = get_test_notebook() |
2085 | - notebook.get_store(Path(':')).dir = Dir('/foo/bar') # fake source dir |
2086 | - notebook.index.update() |
2087 | + notebook = tests.new_notebook(fakedir='/foo/bar') |
2088 | + |
2089 | exporter = Exporter(notebook, **self.options) |
2090 | exporter.export_all(self.dir) |
2091 | |
2092 | @@ -75,10 +73,10 @@ |
2093 | class TestExportCommandLine(TestExportFullOptions): |
2094 | |
2095 | def export(self): |
2096 | - dir = Dir(create_tmp_dir('export_SourceFiles')) |
2097 | + dir = Dir(self.create_tmp_dir('source_files')) |
2098 | init_notebook(dir) |
2099 | notebook = Notebook(dir=dir) |
2100 | - for name, text in get_test_data('wiki'): |
2101 | + for name, text in tests.WikiTestData: |
2102 | page = notebook.get_page(Path(name)) |
2103 | page.parse('wiki', text) |
2104 | notebook.store_page(page) |
2105 | @@ -94,21 +92,18 @@ |
2106 | # TODO test export single page from command line |
2107 | |
2108 | |
2109 | -class TestExportDialog(TestCase): |
2110 | - |
2111 | - slowTest = True |
2112 | +@tests.slowTest |
2113 | +class TestExportDialog(tests.TestCase): |
2114 | |
2115 | def runTest(self): |
2116 | '''Test ExportDialog''' |
2117 | from zim.gui.exportdialog import ExportDialog |
2118 | |
2119 | - dir = Dir(create_tmp_dir('export_ExportDialog')) |
2120 | - |
2121 | - notebook = get_test_notebook() |
2122 | - notebook.get_store(Path(':')).dir = Dir('/foo/bar') # fake source dir |
2123 | - notebook.index.update() |
2124 | - |
2125 | - ui = MockObject() |
2126 | + dir = Dir(self.create_tmp_dir()) |
2127 | + |
2128 | + notebook = tests.new_notebook(fakedir='/foo/bar') |
2129 | + |
2130 | + ui = tests.MockObject() |
2131 | ui.notebook = notebook |
2132 | ui.page = Path('foo') |
2133 | ui.mainwindow = None |
2134 | |
2135 | === modified file 'tests/formats.py' |
2136 | --- tests/formats.py 2011-02-19 16:27:44 +0000 |
2137 | +++ tests/formats.py 2011-06-04 21:27:03 +0000 |
2138 | @@ -6,18 +6,20 @@ |
2139 | |
2140 | from __future__ import with_statement |
2141 | |
2142 | -from tests import TestCase, get_test_data_page, get_test_page, LoggingFilter |
2143 | + |
2144 | +import tests |
2145 | |
2146 | from zim.formats import * |
2147 | -from zim.notebook import Link |
2148 | +from zim.notebook import Path, Link |
2149 | from zim.parsing import link_type |
2150 | |
2151 | if not ElementTreeModule.__name__.endswith('cElementTree'): |
2152 | print 'WARNING: using ElementTree instead of cElementTree' |
2153 | |
2154 | -wikitext = get_test_data_page('wiki', 'roundtrip') |
2155 | - |
2156 | -class TestParseTree(TestCase): |
2157 | +wikitext = tests.WikiTestData.get('roundtrip') |
2158 | + |
2159 | + |
2160 | +class TestParseTree(tests.TestCase): |
2161 | |
2162 | def setUp(self): |
2163 | self.xml = '''\ |
2164 | @@ -41,7 +43,7 @@ |
2165 | e = tree.getroot() |
2166 | self.assertEqual(e.tag, 'zim-tree') # check content |
2167 | text = tree.tostring() |
2168 | - self.assertEqualDiff(text, self.xml) |
2169 | + self.assertEqual(text, self.xml) |
2170 | |
2171 | def testcleanup_headings(self): |
2172 | '''Test ParseTree.cleanup_headings()''' |
2173 | @@ -60,7 +62,7 @@ |
2174 | </zim-tree>''' |
2175 | tree.cleanup_headings(offset=1, max=4) |
2176 | text = tree.tostring() |
2177 | - self.assertEqualDiff(text, wanted) |
2178 | + self.assertEqual(text, wanted) |
2179 | |
2180 | def testSetHeading(self): |
2181 | '''Test ParseTree.set_heading()''' |
2182 | @@ -79,7 +81,7 @@ |
2183 | <h level="6">Head 8</h> |
2184 | </zim-tree>''' |
2185 | text = tree.tostring() |
2186 | - self.assertEqualDiff(text, wanted) |
2187 | + self.assertEqual(text, wanted) |
2188 | |
2189 | def testExtend(self): |
2190 | tree1 = ParseTree().fromstring(self.xml) |
2191 | @@ -107,13 +109,30 @@ |
2192 | <h level="6">Head 8</h> |
2193 | </zim-tree>''' |
2194 | text = tree.tostring() |
2195 | - self.assertEqualDiff(text, wanted) |
2196 | - |
2197 | -class TestTextFormat(TestCase): |
2198 | + self.assertEqual(text, wanted) |
2199 | + |
2200 | + |
2201 | + def testGetEndsWithNewline(self): |
2202 | + for xml, newline in ( |
2203 | + ('<zim-tree partial="True">foo</zim-tree>', False), |
2204 | + ('<zim-tree partial="True"><strong>foo</strong></zim-tree>', False), |
2205 | + ('<zim-tree partial="True"><strong>foo</strong>\n</zim-tree>', True), |
2206 | + ('<zim-tree partial="True"><strong>foo\n</strong></zim-tree>', True), |
2207 | + ('<zim-tree partial="True"><strong>foo</strong>\n<img src="foo"></img></zim-tree>', False), |
2208 | + ('<zim-tree partial="True"><li bullet="unchecked-box" indent="0">foo</li></zim-tree>', True), |
2209 | + ('<zim-tree partial="True"><li bullet="unchecked-box" indent="0"><strong>foo</strong></li></zim-tree>', True), |
2210 | + ('<zim-tree partial="True"><li bullet="unchecked-box" indent="0"><strong>foo</strong></li></zim-tree>', True), |
2211 | + ): |
2212 | + tree = ParseTree().fromstring(xml) |
2213 | + self.assertEqual(tree.get_ends_with_newline(), newline) |
2214 | + |
2215 | + |
2216 | +class TestTextFormat(tests.TestCase): |
2217 | |
2218 | def setUp(self): |
2219 | self.format = get_format('plain') |
2220 | - notebook, self.page = get_test_page() |
2221 | + notebook = tests.new_notebook() |
2222 | + self.page = notebook.get_page(Path('Foo')) |
2223 | |
2224 | def testRoundtrip(self): |
2225 | '''Test roundtrip for plain text''' |
2226 | @@ -123,8 +142,8 @@ |
2227 | #~ print '>>>\n'+tree.tostring()+'\n<<<\n' |
2228 | xml = tree.tostring() |
2229 | output = self.format.Dumper().dump(tree) |
2230 | - self.assertEqualDiff(tree.tostring(), xml) # check tree not modified |
2231 | - self.assertEqualDiff(output, wikitext.splitlines(True)) |
2232 | + self.assertEqual(tree.tostring(), xml) # check tree not modified |
2233 | + self.assertEqual(output, wikitext.splitlines(True)) |
2234 | |
2235 | def testDumping(self): |
2236 | '''Test dumping page to plain text''' |
2237 | @@ -153,6 +172,7 @@ |
2238 | IMAGE: Foo Bar |
2239 | LINKS: :foo:bar ./file.png file:///etc/passwd |
2240 | LINKS: FooBar |
2241 | +TAGS: @foo @bar |
2242 | |
2243 | Some indented |
2244 | paragraphs go here ... |
2245 | @@ -193,7 +213,7 @@ |
2246 | |
2247 | That's all ... |
2248 | ''' |
2249 | - self.assertEqualDiff(text, wanted.splitlines(True)) |
2250 | + self.assertEqual(text, wanted.splitlines(True)) |
2251 | |
2252 | |
2253 | class TestWikiFormat(TestTextFormat): |
2254 | @@ -201,7 +221,9 @@ |
2255 | def setUp(self): |
2256 | #~ TestTextFormat.setUp(self) |
2257 | self.format = get_format('wiki') |
2258 | - notebook, self.page = get_test_page() |
2259 | + notebook = tests.new_notebook() |
2260 | + self.page = notebook.get_page(Path('Foo')) |
2261 | + |
2262 | |
2263 | def testRoundtrip(self): |
2264 | '''Test roundtrip for wiki text''' |
2265 | @@ -224,7 +246,7 @@ |
2266 | #~ print '>>>\n'+tostring(tree)+'\n<<<\n' |
2267 | #~ self.assertEquals(tree.getroot().attrib['Content-Type'], 'text/x-zim-wiki') |
2268 | #~ output = self.format.Dumper().dump(tree) |
2269 | - #~ self.assertEqualDiff(output, text.splitlines(True)) |
2270 | + #~ self.assertEqual(output, text.splitlines(True)) |
2271 | |
2272 | def testParsing(self): |
2273 | '''Test wiki parse tree generation.''' |
2274 | @@ -252,6 +274,7 @@ |
2275 | <p>IMAGE: <img src="../my-image.png" width="600">Foo Bar</img> |
2276 | LINKS: <link href=":foo:bar">:foo:bar</link> <link href="./file.png">./file.png</link> <link href="file:///etc/passwd">file:///etc/passwd</link> |
2277 | LINKS: <link href="Foo">Foo</link><link href="Bar">Bar</link> |
2278 | +TAGS: <tag name="foo">@foo</tag> <tag name="bar">@bar</tag> |
2279 | </p> |
2280 | <p><div indent="1">Some indented |
2281 | paragraphs go here ... |
2282 | @@ -279,7 +302,7 @@ |
2283 | <p>That's all ... |
2284 | </p></zim-tree>''' |
2285 | t = self.format.Parser().parse(wikitext) |
2286 | - self.assertEqualDiff(t.tostring(), tree) |
2287 | + self.assertEqual(t.tostring(), tree) |
2288 | |
2289 | def testUnicodeBullet(self): |
2290 | '''Test support for unicode bullets in source''' |
2291 | @@ -297,7 +320,7 @@ |
2292 | ''' |
2293 | tree = self.format.Parser().parse(input) |
2294 | output = self.format.Dumper().dump(tree) |
2295 | - self.assertEqualDiff(output, text.splitlines(True)) |
2296 | + self.assertEqual(output, text.splitlines(True)) |
2297 | |
2298 | def testLink(self): |
2299 | '''Test iterator function for link''' |
2300 | @@ -340,16 +363,17 @@ |
2301 | <p>test 4 5 6 |
2302 | </p></zim-tree>''' |
2303 | t = self.format.Parser(version='Unknown').parse(input) |
2304 | - self.assertEqualDiff(t.tostring(), xml) |
2305 | + self.assertEqual(t.tostring(), xml) |
2306 | output = self.format.Dumper().dump(t) |
2307 | - self.assertEqualDiff(output, wanted.splitlines(True)) |
2308 | - |
2309 | - |
2310 | -class TestHtmlFormat(TestCase): |
2311 | + self.assertEqual(output, wanted.splitlines(True)) |
2312 | + |
2313 | + |
2314 | +class TestHtmlFormat(tests.TestCase): |
2315 | |
2316 | def setUp(self): |
2317 | self.format = get_format('html') |
2318 | - notebook, self.page = get_test_page() |
2319 | + notebook = tests.new_notebook() |
2320 | + self.page = notebook.get_page(Path('Foo')) |
2321 | |
2322 | def testEncoding(self): |
2323 | '''Test HTML encoding''' |
2324 | @@ -399,6 +423,7 @@ |
2325 | IMAGE: <img src="img://../my-image.png" alt="Foo Bar" width="600"><br> |
2326 | LINKS: <a href="page://:foo:bar" title=":foo:bar">:foo:bar</a> <a href="file://./file.png" title="./file.png">./file.png</a> <a href="file://file:///etc/passwd" title="file:///etc/passwd">file:///etc/passwd</a><br> |
2327 | LINKS: <a href="page://Foo" title="Foo">Foo</a><a href="page://Bar" title="Bar">Bar</a><br> |
2328 | +TAGS: <span class="zim-tag">@foo</span> <span class="zim-tag">@bar</span><br> |
2329 | </p> |
2330 | |
2331 | <p> |
2332 | @@ -478,16 +503,16 @@ |
2333 | That's all ...<br> |
2334 | </p> |
2335 | ''' |
2336 | - self.assertEqualDiff(output, html.splitlines(True)) |
2337 | - |
2338 | - |
2339 | -class LatexLoggingFilter(LoggingFilter): |
2340 | + self.assertEqual(output, html.splitlines(True)) |
2341 | + |
2342 | + |
2343 | +class LatexLoggingFilter(tests.LoggingFilter): |
2344 | |
2345 | logger = 'zim.formats.latex' |
2346 | message = 'No document type set in template' |
2347 | |
2348 | |
2349 | -class TestLatexFormat(TestCase): |
2350 | +class TestLatexFormat(tests.TestCase): |
2351 | |
2352 | def testEncode(self): |
2353 | '''test the escaping of certain characters''' |
2354 | @@ -501,7 +526,7 @@ |
2355 | '''test the export of a wiki page to latex''' |
2356 | with LatexLoggingFilter(): |
2357 | format = get_format('LaTeX') |
2358 | - testpage = get_test_data_page('wiki','Test:wiki') |
2359 | + testpage = tests.WikiTestData.get('Test:wiki') |
2360 | tree = get_format('wiki').Parser().parse(testpage) |
2361 | output = format.Dumper(linker=StubLinker()).dump(tree) |
2362 | self.assertTrue('\chapter{Foo Bar}\n' in output) |
2363 | @@ -520,7 +545,7 @@ |
2364 | def icon(self, name): return 'icon://' + name |
2365 | |
2366 | |
2367 | -class TestParseTreeBuilder(TestCase): |
2368 | +class TestParseTreeBuilder(tests.TestCase): |
2369 | |
2370 | def runTest(self): |
2371 | '''Test ParseTreeBuilder class''' |
2372 | @@ -579,5 +604,4 @@ |
2373 | builder.feed(input) |
2374 | root = builder.close() |
2375 | tree = ParseTree(root) |
2376 | - self.assertEqualDiff(tree.tostring(), wanted) |
2377 | - |
2378 | + self.assertEqual(tree.tostring(), wanted) |
2379 | |
2380 | === modified file 'tests/fs.py' |
2381 | --- tests/fs.py 2011-02-19 16:27:44 +0000 |
2382 | +++ tests/fs.py 2011-06-04 21:27:03 +0000 |
2383 | @@ -11,6 +11,7 @@ |
2384 | import os |
2385 | import time |
2386 | |
2387 | +import zim.fs |
2388 | from zim.fs import * |
2389 | from zim.fs import Path, FileHandle, FileWriteError, TmpFile, get_tmpdir, normalize_win32_share, PathLookupError, FileNotFoundError, FilteredDir, isabs, joinpath |
2390 | from zim.errors import Error |
2391 | @@ -118,7 +119,7 @@ |
2392 | def testFileHandle(self): |
2393 | '''Test FileHandle object''' |
2394 | self.on_close_called = False |
2395 | - tmpdir = tests.create_tmp_dir('fs_testFile') |
2396 | + tmpdir = self.create_tmp_dir('testFileHandle') |
2397 | fh = FileHandle( |
2398 | tmpdir+'/foo.txt', mode='w', on_close=self.on_close) |
2399 | fh.write('duss') |
2400 | @@ -130,7 +131,7 @@ |
2401 | |
2402 | def testFile(self): |
2403 | '''Test File object''' |
2404 | - tmpdir = tests.create_tmp_dir('fs_testFile') |
2405 | + tmpdir = self.create_tmp_dir('testFile') |
2406 | file = File(tmpdir+'/foo/bar/baz.txt') |
2407 | assert not file.exists() |
2408 | file.touch() |
2409 | @@ -230,7 +231,7 @@ |
2410 | |
2411 | def testDir(self): |
2412 | '''Test Dir object''' |
2413 | - tmpdir = tests.create_tmp_dir('fs_testDir') |
2414 | + tmpdir = self.create_tmp_dir('testDir') |
2415 | dir = Dir(tmpdir+'/foo/bar') |
2416 | assert not dir.exists() |
2417 | |
2418 | @@ -261,12 +262,22 @@ |
2419 | |
2420 | self.assertEqual(File((dir, 'foo.txt')), dir.file('foo.txt')) |
2421 | self.assertEqual(dir.file(File((dir, 'foo.txt'))), dir.file('foo.txt')) |
2422 | + self.assertEqual(dir.file(Path((dir, 'foo.txt'))), dir.file('foo.txt')) |
2423 | + self.assertEqual(dir.file(('foo.txt',)), dir.file('foo.txt')) |
2424 | self.assertRaises(PathLookupError, dir.file, File('/foo/bar.txt')) # not below dir |
2425 | |
2426 | + self.assertEqual(dir.resolve_file('../foo.txt'), dir.dir.file('foo.txt')) |
2427 | + self.assertEqual(dir.resolve_file(File('/foo/bar.txt')), File('/foo/bar.txt')) |
2428 | + |
2429 | self.assertEqual(Dir((dir, 'bar')), dir.subdir('bar')) |
2430 | self.assertEqual(dir.subdir(Dir((dir, 'bar'))), dir.subdir('bar')) |
2431 | + self.assertEqual(dir.subdir(Path((dir, 'bar'))), dir.subdir('bar')) |
2432 | + self.assertEqual(dir.subdir(('bar',)), dir.subdir('bar')) |
2433 | self.assertRaises(PathLookupError, dir.subdir, Dir('/foo/bar')) # not below dir |
2434 | |
2435 | + self.assertEqual(dir.resolve_dir('../bar'), dir.dir.subdir('bar')) |
2436 | + self.assertEqual(dir.resolve_dir(Dir('/foo/bar')), Dir('/foo/bar')) |
2437 | + |
2438 | self.assertRaises(OSError, dir.remove) # dir not empty |
2439 | self.assertTrue(dir.exists()) |
2440 | dir.cleanup() |
2441 | @@ -279,12 +290,11 @@ |
2442 | self.assertEqual(dir.list(), []) # list non-existing dir |
2443 | |
2444 | |
2445 | +@tests.slowTest |
2446 | class TestFileOverwrite(tests.TestCase): |
2447 | |
2448 | - slowTest = True |
2449 | - |
2450 | def setUp(self): |
2451 | - self.path = tests.create_tmp_dir('fs_testOverwrite')+'/file.txt' |
2452 | + self.path = self.create_tmp_dir()+'/file.txt' |
2453 | |
2454 | def modify(self, func): |
2455 | mtime = os.stat(self.path).st_mtime |
2456 | @@ -329,22 +339,15 @@ |
2457 | self.assertEquals(file.read(), 'foo') |
2458 | |
2459 | |
2460 | +@tests.slowTest |
2461 | +@tests.skipUnless(hasattr(os, 'symlink'), 'OS does not supprot symlinks') |
2462 | class TestSymlinks(tests.TestCase): |
2463 | |
2464 | - slowTest = True |
2465 | - |
2466 | - @staticmethod |
2467 | - def skipTest(): |
2468 | - if not hasattr(os, 'symlink'): |
2469 | - return 'OS does not supprot symlinks' |
2470 | - else: |
2471 | - return False |
2472 | - |
2473 | def runTest(self): |
2474 | '''Test file operations are safe for symlinks''' |
2475 | |
2476 | # Set up a file structue with a symlink |
2477 | - tmpdir = tests.create_tmp_dir('fs_TestSymLinks') |
2478 | + tmpdir = self.create_tmp_dir() |
2479 | targetdir = Dir(tmpdir + '/target') |
2480 | targetdir.file('foo.txt').touch() |
2481 | targetfile = File(tmpdir + '/target.txt') |
2482 | @@ -383,3 +386,28 @@ |
2483 | self.assertEqual(dir.list(), []) |
2484 | self.assertTrue(targetdir.exists()) |
2485 | self.assertEqual(targetdir.list(), ['foo.txt']) |
2486 | + |
2487 | + |
2488 | +@tests.slowTest |
2489 | +@tests.skipUnless(zim.fs.gio, 'Trashing not supported, \'gio\' is missing') |
2490 | +class TestTrash(tests.TestCase): |
2491 | + |
2492 | + def runTest(self): |
2493 | + '''Test trashing files and folders''' |
2494 | + root = Dir(self.create_tmp_dir()) |
2495 | + file = root.file('test.txt') |
2496 | + file.touch() |
2497 | + self.assertTrue(file.exists()) |
2498 | + self.assertTrue(file.trash()) |
2499 | + self.assertFalse(file.exists()) |
2500 | + dir = root.subdir('test') |
2501 | + dir.touch() |
2502 | + self.assertTrue(dir.exists()) |
2503 | + self.assertTrue(dir.trash()) |
2504 | + self.assertFalse(dir.exists()) |
2505 | + |
2506 | + # fails silent if file does not exist |
2507 | + self.assertFalse(file.trash()) |
2508 | + self.assertFalse(dir.trash()) |
2509 | + |
2510 | + # How can we cause gio to give an error and test that case ?? |
2511 | |
2512 | === modified file 'tests/gui.py' |
2513 | --- tests/gui.py 2011-02-14 20:22:50 +0000 |
2514 | +++ tests/gui.py 2011-06-04 21:27:03 +0000 |
2515 | @@ -1,23 +1,31 @@ |
2516 | - |
2517 | -from tests import TestCase, get_test_notebook, create_tmp_dir, MockObject |
2518 | +# -*- coding: utf-8 -*- |
2519 | + |
2520 | +# Copyright 2009 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
2521 | + |
2522 | +from __future__ import with_statement |
2523 | + |
2524 | +import tests |
2525 | + |
2526 | |
2527 | from zim.errors import Error |
2528 | -from zim.notebook import Path |
2529 | +from zim.notebook import get_notebook_list, Path, NotebookInfo |
2530 | from zim.fs import File, Dir |
2531 | +from zim.config import config_file |
2532 | |
2533 | import zim.gui |
2534 | |
2535 | from zim.gui.clipboard import * |
2536 | |
2537 | |
2538 | -class TestClipboard(TestCase): |
2539 | +@tests.slowTest |
2540 | +class TestClipboard(tests.TestCase): |
2541 | |
2542 | def runTest(self): |
2543 | '''Test clipboard interaction''' |
2544 | + path = self.get_tmp_name() |
2545 | + notebook = tests.new_notebook(fakedir=path) |
2546 | + |
2547 | clipboard = Clipboard() |
2548 | - notebook = get_test_notebook() |
2549 | - tmp_dir = create_tmp_dir('gui_Clipboard') |
2550 | - notebook.get_store(Path(':')).dir = Dir(tmp_dir) # fake source dir |
2551 | |
2552 | # tree roundtrip |
2553 | for pagename in ('Test:wiki', 'roundtrip'): |
2554 | @@ -36,7 +44,7 @@ |
2555 | |
2556 | wanted = 'some **bold** text\n' |
2557 | text = clipboard.wait_for_text() |
2558 | - self.assertEqualDiff(text, wanted) |
2559 | + self.assertEqual(text, wanted) |
2560 | |
2561 | wanted = '''\ |
2562 | <html> |
2563 | @@ -54,7 +62,7 @@ |
2564 | </html> |
2565 | ''' |
2566 | selection = clipboard.wait_for_contents('text/html') |
2567 | - self.assertEqualDiff(selection.data, wanted) |
2568 | + self.assertEqual(selection.data, wanted) |
2569 | |
2570 | wanted = '''\ |
2571 | Version:1.0\r |
2572 | @@ -72,7 +80,7 @@ |
2573 | </p> |
2574 | <!--EndFragment--></BODY></HTML>''' |
2575 | selection = clipboard.wait_for_contents('HTML Format') |
2576 | - self.assertEqualDiff(selection.data, wanted) |
2577 | + self.assertEqual(selection.data, wanted) |
2578 | |
2579 | |
2580 | # pagelink -> .. |
2581 | @@ -153,12 +161,12 @@ |
2582 | self.assertEqual(notebook.resolve_file(rel_path, page), file_obj) |
2583 | |
2584 | |
2585 | -class TestDialogs(TestCase): |
2586 | - |
2587 | - slowTest = True |
2588 | +@tests.slowTest |
2589 | +class TestDialogs(tests.TestCase): |
2590 | |
2591 | def setUp(self): |
2592 | - self.ui = MockUI('Test:foo:bar') |
2593 | + path = self.create_tmp_dir() |
2594 | + self.ui = MockUI('Test:foo:bar', fakedir=path) |
2595 | |
2596 | def testOpenPageDialog(self): |
2597 | '''Test OpenPageDialog dialog (Jump To...)''' |
2598 | @@ -213,7 +221,7 @@ |
2599 | |
2600 | def testSaveCopyDialog(self): |
2601 | '''Test SaveCopyDialog''' |
2602 | - tmp_dir = create_tmp_dir('gui_SaveCopyDialog') |
2603 | + tmp_dir = self.create_tmp_dir('testSaveCopyDialog') |
2604 | file = File((tmp_dir, 'save_copy.txt')) |
2605 | self.assertFalse(file.exists()) |
2606 | dialog = zim.gui.SaveCopyDialog(self.ui) |
2607 | @@ -223,11 +231,10 @@ |
2608 | |
2609 | def testImportPageDialog(self): |
2610 | '''Test ImportPageDialog''' |
2611 | - tmp_dir = create_tmp_dir('gui_ImportPageDialog') |
2612 | + tmp_dir = self.create_tmp_dir('testImportPageDialog') |
2613 | file = File((tmp_dir, 'import_page.txt')) |
2614 | file.write('test 123\n') |
2615 | self.assertTrue(file.exists()) |
2616 | - self.ui = MockUI() |
2617 | dialog = zim.gui.ImportPageDialog(self.ui) |
2618 | dialog.set_file(file) |
2619 | #~ dialog.assert_response_ok() |
2620 | @@ -295,15 +302,13 @@ |
2621 | |
2622 | def testAttachFileDialog(self): |
2623 | '''Test AttachFileDialog''' |
2624 | - tmp_dir = create_tmp_dir('gui_AttachFileDialog') |
2625 | + tmp_dir = self.create_tmp_dir('testAttachFileDialog') |
2626 | file = File((tmp_dir, 'file_to_be_attached')) |
2627 | file.write('Test 1 2 3\n') |
2628 | newfile = File((tmp_dir, 'attachments', 'Test', 'foo', 'file_to_be_attached')) |
2629 | self.assertTrue(file.exists()) |
2630 | self.assertFalse(newfile.exists()) |
2631 | |
2632 | - store = self.ui.notebook.get_store(Path(':')) |
2633 | - store.dir = Dir((tmp_dir, 'attachments')) # Fake dir based notebook |
2634 | dialog = zim.gui.AttachFileDialog(self.ui, path=Path('Test:foo')) |
2635 | dialog.set_file(file) |
2636 | #~ dialog.assert_response_ok() |
2637 | @@ -311,20 +316,19 @@ |
2638 | #~ self.assertTrue(file.exists()) # No move or delete happened |
2639 | #~ self.assertTrue(newfile.exists()) |
2640 | #~ self.assertTrue(newfile.compare(file)) |
2641 | - #~ del store.dir |
2642 | |
2643 | def testSearchDialog(self): |
2644 | '''Test SearchDialog''' |
2645 | from zim.gui.searchdialog import SearchDialog |
2646 | - self.ui.notebook = get_test_notebook() |
2647 | + self.ui.notebook = tests.new_notebook() |
2648 | dialog = SearchDialog(self.ui) |
2649 | dialog.query_entry.set_text('Foo') |
2650 | dialog.query_entry.activate() |
2651 | model = dialog.results_treeview.get_model() |
2652 | self.assertTrue(len(model) > 3) |
2653 | |
2654 | - self.ui.mainwindow = MockObject() |
2655 | - self.ui.mainwindow.pageview = MockObject() |
2656 | + self.ui.mainwindow = tests.MockObject() |
2657 | + self.ui.mainwindow.pageview = tests.MockObject() |
2658 | col = dialog.results_treeview.get_column(0) |
2659 | dialog.results_treeview.row_activated((0,), col) |
2660 | |
2661 | @@ -380,8 +384,52 @@ |
2662 | def testPropertiesDialog(self): |
2663 | '''Test PropertiesDialog''' |
2664 | from zim.gui.propertiesdialog import PropertiesDialog |
2665 | - dialog = PropertiesDialog(self.ui) |
2666 | - dialog.assert_response_ok() |
2667 | + self.ui.readonly = True |
2668 | + dialog = PropertiesDialog(self.ui) |
2669 | + dialog.assert_response_ok() |
2670 | + |
2671 | + from zim.config import ConfigDictFile |
2672 | + notebook = self.ui.notebook |
2673 | + file = notebook.dir.file('notebook.zim') |
2674 | + notebook.config = ConfigDictFile(file) |
2675 | + self.ui.readonly = False |
2676 | + |
2677 | + config1 = { |
2678 | + 'name': 'Notebook Foo', |
2679 | + 'home': 'Home', |
2680 | + 'icon': './icon.png', |
2681 | + 'document_root': '/foo', |
2682 | + 'shared': False, |
2683 | + } |
2684 | + config2 = { |
2685 | + 'name': 'Notebook Bar', |
2686 | + 'home': 'HomeSweetHome', |
2687 | + 'icon': './picture.png', |
2688 | + 'document_root': '/bar', |
2689 | + 'shared': True, |
2690 | + } |
2691 | + notebook.save_properties(**config1) |
2692 | + self.assertEqual(notebook.config['Notebook'], config1) |
2693 | + |
2694 | + dialog = PropertiesDialog(self.ui) |
2695 | + dialog.assert_response_ok() |
2696 | + |
2697 | + self.assertEqual(notebook.config['Notebook'], config1) |
2698 | + self.assertEqual(notebook.name, config1['name']) |
2699 | + self.assertEqual(notebook.get_home_page(), Path(config1['home'])) |
2700 | + self.assertEqual(notebook.icon, notebook.dir.file(config1['icon']).path) |
2701 | + self.assertEqual(notebook.document_root, Dir(config1['document_root'])) |
2702 | + |
2703 | + dialog = PropertiesDialog(self.ui) |
2704 | + dialog.form.update(config2) |
2705 | + dialog.assert_response_ok() |
2706 | + |
2707 | + self.assertEqual(notebook.config['Notebook'], config2) |
2708 | + self.assertEqual(notebook.name, config2['name']) |
2709 | + self.assertEqual(notebook.get_home_page(), Path(config2['home'])) |
2710 | + self.assertEqual(notebook.icon, notebook.dir.file(config2['icon']).path) |
2711 | + self.assertEqual(notebook.document_root, Dir(config2['document_root'])) |
2712 | + |
2713 | |
2714 | def testPreferencesDialog(self): |
2715 | '''Test PreferencesDialog''' |
2716 | @@ -432,14 +480,114 @@ |
2717 | |
2718 | |
2719 | # Test for ExportDialog can be found in test/export.py |
2720 | - |
2721 | - |
2722 | -class MockUI(MockObject): |
2723 | - |
2724 | - tmp_dir = create_tmp_dir('gui_MockUI') |
2725 | - |
2726 | - def __init__(self, page=None): |
2727 | - MockObject.__init__(self) |
2728 | + # Test for NotebookDialog is in separate class below |
2729 | + |
2730 | + |
2731 | +@tests.slowTest |
2732 | +class TestGtkInterface(tests.TestCase): |
2733 | + |
2734 | + def runTest(self): |
2735 | + ui = zim.gui.GtkInterface() |
2736 | + |
2737 | + # test populating menus |
2738 | + menu = gtk.Menu() |
2739 | + ui.populate_popup('page_popup', menu) |
2740 | + items = menu.get_children() |
2741 | + self.assertTrue(len(items) > 3) |
2742 | + |
2743 | + |
2744 | +@tests.slowTest |
2745 | +class TestNotebookDialog(tests.TestCase): |
2746 | + |
2747 | + def setUp(self): |
2748 | + list = config_file('notebooks.list') |
2749 | + file = list.file |
2750 | + if file.exists(): |
2751 | + file.remove() |
2752 | + |
2753 | + def runTest(self): |
2754 | + from zim.gui.notebookdialog import prompt_notebook, \ |
2755 | + AddNotebookDialog, NotebookDialog |
2756 | + |
2757 | + tmpdir = self.create_tmp_dir() |
2758 | + dir1 = Dir(tmpdir + '/mynotebook1') |
2759 | + dir2 = Dir(tmpdir + '/mynotebook2') |
2760 | + |
2761 | + # First time we get directly the AddNotebookDialog |
2762 | + def doAddNotebook(dialog): |
2763 | + self.assertTrue(isinstance(dialog, AddNotebookDialog)) |
2764 | + dialog.form['name'] = 'Foo' |
2765 | + dialog.form['folder'] = dir1.path |
2766 | + dialog.assert_response_ok() |
2767 | + |
2768 | + with tests.DialogContext(doAddNotebook): |
2769 | + self.assertEqual(prompt_notebook(), dir1.uri) |
2770 | + |
2771 | + # Second time we get the list |
2772 | + def testNotebookDialog(dialog): |
2773 | + self.assertTrue(isinstance(dialog, NotebookDialog)) |
2774 | + selection = dialog.treeview.get_selection() |
2775 | + selection.select_path((0,)) # select first and only notebook |
2776 | + dialog.assert_response_ok() |
2777 | + |
2778 | + with tests.DialogContext(testNotebookDialog): |
2779 | + self.assertEqual(prompt_notebook(), dir1.uri) |
2780 | + |
2781 | + # Third time we add a notebook and set the default |
2782 | + def doAddNotebook(dialog): |
2783 | + self.assertTrue(isinstance(dialog, AddNotebookDialog)) |
2784 | + dialog.form['name'] = 'Bar' |
2785 | + dialog.form['folder'] = dir2.path |
2786 | + dialog.assert_response_ok() |
2787 | + |
2788 | + def testAddNotebook(dialog): |
2789 | + self.assertTrue(isinstance(dialog, NotebookDialog)) |
2790 | + |
2791 | + with tests.DialogContext(doAddNotebook): |
2792 | + dialog.do_add_notebook() |
2793 | + |
2794 | + dialog.combobox.set_active(0) |
2795 | + |
2796 | + selection = dialog.treeview.get_selection() |
2797 | + selection.select_path((1,)) # select newly added notebook |
2798 | + dialog.assert_response_ok() |
2799 | + |
2800 | + with tests.DialogContext(testAddNotebook): |
2801 | + self.assertEqual(prompt_notebook(), dir2.uri) |
2802 | + |
2803 | + # Check the notebook exists and the notebook list looks like it should |
2804 | + for dir in (dir1, dir2): |
2805 | + self.assertTrue(dir.exists()) |
2806 | + self.assertTrue(dir.file('notebook.zim').exists()) |
2807 | + |
2808 | + list = get_notebook_list() |
2809 | + self.assertTrue(len(list) == 2) |
2810 | + self.assertEqual(list[0], NotebookInfo(dir1.uri, name='Foo')) |
2811 | + self.assertEqual(list[1], NotebookInfo(dir2.uri, name='Bar')) |
2812 | + self.assertEqual(list.default, NotebookInfo(dir1.uri, name='Foo')) |
2813 | + |
2814 | + # Now unset the default and again check the notebook list |
2815 | + def unsetDefault(dialog): |
2816 | + self.assertTrue(isinstance(dialog, NotebookDialog)) |
2817 | + dialog.combobox.set_active(-1) |
2818 | + selection = dialog.treeview.get_selection() |
2819 | + selection.select_path((1,)) # select newly added notebook |
2820 | + dialog.assert_response_ok() |
2821 | + |
2822 | + with tests.DialogContext(unsetDefault): |
2823 | + self.assertEqual(prompt_notebook(), dir2.uri) |
2824 | + |
2825 | + list = get_notebook_list() |
2826 | + self.assertTrue(len(list) == 2) |
2827 | + self.assertTrue(list.default is None) |
2828 | + |
2829 | + |
2830 | +class MockUI(tests.MockObject): |
2831 | + |
2832 | + def __init__(self, page=None, fakedir=None): |
2833 | + tests.MockObject.__init__(self) |
2834 | + |
2835 | + self.tmp_dir = self.create_tmp_dir() |
2836 | |
2837 | if page and not isinstance(page, Path): |
2838 | self.page = Path(page) |
2839 | @@ -447,6 +595,4 @@ |
2840 | self.page = page |
2841 | |
2842 | self.mainwindow = None |
2843 | - self.notebook = get_test_notebook() |
2844 | - self.notebook.get_store(Path(':')).dir = Dir(self.tmp_dir) # fake source dir |
2845 | - |
2846 | + self.notebook = tests.new_notebook(fakedir=fakedir) |
2847 | |
2848 | === modified file 'tests/history.py' |
2849 | --- tests/history.py 2011-02-19 16:27:44 +0000 |
2850 | +++ tests/history.py 2011-06-04 21:27:03 +0000 |
2851 | @@ -2,18 +2,20 @@ |
2852 | |
2853 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
2854 | |
2855 | -from tests import TestCase, get_test_notebook |
2856 | +import tests |
2857 | + |
2858 | |
2859 | import zim.history |
2860 | from zim.history import History, HistoryPath |
2861 | from zim.notebook import Path |
2862 | from zim.config import ConfigDict |
2863 | |
2864 | -class TestHistory(TestCase): |
2865 | + |
2866 | +class TestHistory(tests.TestCase): |
2867 | |
2868 | def setUp(self): |
2869 | zim.history.MAX_HISTORY = 100 |
2870 | - self.notebook = get_test_notebook() |
2871 | + self.notebook = tests.new_notebook() |
2872 | self.pages = [self.notebook.get_page(Path(name)) |
2873 | for name in self.notebook.testdata_manifest] |
2874 | |
2875 | |
2876 | === modified file 'tests/index.py' |
2877 | --- tests/index.py 2011-02-19 16:27:44 +0000 |
2878 | +++ tests/index.py 2011-06-04 21:27:03 +0000 |
2879 | @@ -8,31 +8,13 @@ |
2880 | import pango |
2881 | |
2882 | from zim.fs import Dir |
2883 | -from zim.notebook import Notebook, Path, Link, init_notebook |
2884 | +from zim.notebook import Notebook, Path, Link |
2885 | from zim.index import * |
2886 | from zim.gui.pageindex import * |
2887 | from zim.formats import ParseTree |
2888 | |
2889 | -# TODO test n_list_* functions |
2890 | - |
2891 | - |
2892 | -def get_files_notebook(key): |
2893 | - # We fill the notebook using the store interface, as this test comes before |
2894 | - # the notebook test, but after the store test. |
2895 | - dir = Dir(tests.create_tmp_dir('index_'+key)) |
2896 | - init_notebook(dir) |
2897 | - notebook = Notebook(dir=dir) |
2898 | - store = notebook.get_store(':') |
2899 | - manifest = [] |
2900 | - for name, text in tests.get_test_data('wiki'): |
2901 | - manifest.append(name) |
2902 | - page = store.get_page(Path(name)) |
2903 | - page.parse('wiki', text) |
2904 | - store.store_page(page) |
2905 | - notebook.testdata_manifest = tests.expand_manifest(manifest) |
2906 | - return notebook |
2907 | - |
2908 | - |
2909 | + |
2910 | +@tests.slowTest |
2911 | class TestIndex(tests.TestCase): |
2912 | |
2913 | def setUp(self): |
2914 | @@ -40,7 +22,7 @@ |
2915 | # for the notebook. So any assumption from the notebook about |
2916 | # the index will be wrong. |
2917 | self.index = Index(dbfile=':memory:') |
2918 | - self.notebook = tests.get_test_notebook() |
2919 | + self.notebook = tests.new_notebook() |
2920 | self.index.set_notebook(self.notebook) |
2921 | |
2922 | def runTest(self): |
2923 | @@ -96,6 +78,19 @@ |
2924 | n = self.index.n_list_links(Path('Test:foo:bar'), LINK_DIR_BACKWARD) |
2925 | self.assertEqual(n, len(backlist)) |
2926 | |
2927 | + # tags |
2928 | + taglist = list(self.index.list_tags(Path('Test:tags'))) |
2929 | + self.assertTrue(len(taglist) == 11) |
2930 | + for tag in taglist: |
2931 | + self.assertTrue(isinstance(tag, IndexTag)) |
2932 | + tagnames = [t.name for t in taglist] |
2933 | + aretags = ['tags', 'beginning', 'end', 'tabs', 'verbatim', |
2934 | + 'enumerations', 'encoding', 's', 'num6ers', 'wit', 'cr'] |
2935 | + nottags = ['places', 'links', 'captions', 'Headings', 'word'] |
2936 | + for t in aretags: |
2937 | + self.assertTrue(t in tagnames) |
2938 | + for t in nottags: |
2939 | + self.assertTrue(not t in tagnames) |
2940 | |
2941 | # cursor.row_count is not reliable - see docs |
2942 | def count_pages(db): |
2943 | @@ -121,7 +116,7 @@ |
2944 | self.assertTrue(count_pages(self.index.db) >= manifest) |
2945 | origdb = dump_db(self.index.db) |
2946 | self.index.update(checkcontents=False) |
2947 | - self.assertEqualDiff(dump_db(self.index.db), origdb) |
2948 | + self.assertEqual(dump_db(self.index.db), origdb) |
2949 | |
2950 | # indexkey |
2951 | for path in (Path('Test'), Path('Test:foo')): |
2952 | @@ -154,7 +149,7 @@ |
2953 | self.index.flush() |
2954 | self.assertEqual(count_pages(self.index.db), 1) |
2955 | self.index.update() |
2956 | - self.assertEqualDiff(dump_db(self.index.db), origdb) |
2957 | + self.assertEqual(dump_db(self.index.db), origdb) |
2958 | |
2959 | # now index only part of the tree - and repeat |
2960 | self.index.flush() |
2961 | @@ -163,7 +158,7 @@ |
2962 | self.assertTrue(count_pages(self.index.db) > 2) |
2963 | partdb = dump_db(self.index.db) |
2964 | self.index.update(Path('Test')) |
2965 | - self.assertEqualDiff(dump_db(self.index.db), partdb) |
2966 | + self.assertEqual(dump_db(self.index.db), partdb) |
2967 | |
2968 | # Index whole tree again |
2969 | self.index.update() |
2970 | @@ -184,6 +179,13 @@ |
2971 | path = self.index.lookup_path(Path('foo:bar')) |
2972 | self.assertTrue(path) |
2973 | |
2974 | + # Check for tag indexing |
2975 | + tags = [tag.name for tag in self.index.list_tags(Path('roundtrip'))] |
2976 | + for t in ('foo', 'bar'): |
2977 | + self.assertTrue(t in tags) |
2978 | + tagged = list(self.index.list_tagged_pages(t)) |
2979 | + self.assertTrue(Path('roundtrip') in tagged) |
2980 | + |
2981 | tree = ParseTree().fromstring('<zim-tree><link href=":foo:bar">:foo:bar</link></zim-tree>') |
2982 | page = self.notebook.get_page(Path('roundtrip')) |
2983 | page.set_parsetree(tree) |
2984 | @@ -198,13 +200,13 @@ |
2985 | self.assertTrue(path is None) |
2986 | |
2987 | |
2988 | +@tests.slowTest |
2989 | class TestIndexFiles(TestIndex): |
2990 | # Like the test above, but now using a files backend |
2991 | |
2992 | - slowTest = True |
2993 | - |
2994 | def setUp(self): |
2995 | - self.notebook = get_files_notebook('TestIndexFiles') |
2996 | + path = self.create_tmp_dir() |
2997 | + self.notebook = tests.new_files_notebook(path) |
2998 | self.index = self.notebook.index |
2999 | |
3000 | def runTest(self): |
3001 | @@ -221,7 +223,7 @@ |
3002 | |
3003 | def setUp(self): |
3004 | self.index = Index(dbfile=':memory:') |
3005 | - self.notebook = tests.get_test_notebook() |
3006 | + self.notebook = tests.new_notebook() |
3007 | self.index.set_notebook(self.notebook) |
3008 | self.notebook.index.update() |
3009 | |
3010 | @@ -233,22 +235,21 @@ |
3011 | # Hooking up the treeview as well just to see if we get any errors |
3012 | # From the order the signals are generated. |
3013 | |
3014 | - ui = StubUI() |
3015 | + ui = MockUI() |
3016 | + ui.notebook = self.notebook |
3017 | + ui.page = Path('Test:foo') |
3018 | + self.assertTrue(self.notebook.get_page(ui.page).exists()) |
3019 | + |
3020 | treeview = PageTreeView(ui) |
3021 | treestore = PageTreeStore(self.index) |
3022 | self.assertEqual(treestore.get_flags(), 0) |
3023 | self.assertEqual(treestore.get_n_columns(), 5) |
3024 | treeview.set_model(treestore) |
3025 | |
3026 | - def process_events(*a): |
3027 | - while gtk.events_pending(): |
3028 | - gtk.main_iteration(block=False) |
3029 | - return True # continue |
3030 | - |
3031 | - self.index.update(callback=process_events) |
3032 | - process_events() |
3033 | - |
3034 | - treeview = PageTreeView(None) # just run hidden to check errors |
3035 | + self.index.update(callback=tests.gtk_process_events) |
3036 | + tests.gtk_process_events() |
3037 | + |
3038 | + treeview = PageTreeView(ui) # just run hidden to check errors |
3039 | treeview.set_model(treestore) |
3040 | |
3041 | n = treestore.on_iter_n_children(None) |
3042 | @@ -279,10 +280,11 @@ |
3043 | |
3044 | # Now walk through the whole notebook testing the API |
3045 | # with nested pages and stuff |
3046 | - n = 0 |
3047 | + npages = 0 |
3048 | path = [] |
3049 | for page in self.notebook.walk(): |
3050 | - n += 1 |
3051 | + #~ print '>>', page |
3052 | + npages += 1 |
3053 | names = page.name.split(':') |
3054 | if len(names) > len(path): |
3055 | path.append(0) # always increment by one |
3056 | @@ -340,22 +342,41 @@ |
3057 | child = treestore.iter_nth_child(iter, 0) |
3058 | self.assertTrue(child is None) |
3059 | |
3060 | - self.assertTrue(n > 0) # double check sanity of walk() method |
3061 | + self.assertTrue(npages > 10) # double check sanity of walk() method |
3062 | |
3063 | # Check if all the signals go OK |
3064 | - treestore.disconnect() |
3065 | + treestore.disconnect_index() |
3066 | del treestore |
3067 | self.index.flush() |
3068 | treestore = PageTreeStore(self.index) |
3069 | - self.index.update(callback=process_events) |
3070 | - |
3071 | - |
3072 | + treeview = PageTreeView(ui, treestore) |
3073 | + self.index.update(callback=tests.gtk_process_events) |
3074 | + |
3075 | + # Try some TreeView methods |
3076 | + path = Path('Test:foo') |
3077 | + self.assertTrue(treeview.select_page(path)) |
3078 | + self.assertEqual(treeview.get_selected_path(), path) |
3079 | + treepath = treeview.get_model().get_treepath(path) |
3080 | + self.assertTrue(not treepath is None) |
3081 | + col = treeview.get_column(0) |
3082 | + treeview.row_activated(treepath, col) |
3083 | + |
3084 | + #~ treeview.emit('popup-menu') |
3085 | + treeview.emit('insert-link', path) |
3086 | + treeview.emit('copy') |
3087 | + |
3088 | + # Check if all the signals go OK in delete |
3089 | + for page in reversed(list(self.notebook.walk())): # delete bottom up |
3090 | + self.notebook.delete_page(page) |
3091 | + tests.gtk_process_events() |
3092 | + |
3093 | + |
3094 | +@tests.slowTest |
3095 | class TestPageTreeStoreFiles(TestPageTreeStore): |
3096 | |
3097 | - slowTest = True |
3098 | - |
3099 | def setUp(self): |
3100 | - self.notebook = get_files_notebook('TestPageTreeStoreFiles') |
3101 | + path = self.create_tmp_dir() |
3102 | + self.notebook = tests.new_files_notebook(path) |
3103 | self.index = self.notebook.index |
3104 | |
3105 | def runTest(self): |
3106 | @@ -363,13 +384,7 @@ |
3107 | TestPageTreeStore.runTest(self) |
3108 | |
3109 | |
3110 | -class StubUI(object): |
3111 | +class MockUI(tests.MockObject): |
3112 | |
3113 | page = None |
3114 | notebook = None |
3115 | - |
3116 | - def connect(*a): |
3117 | - pass |
3118 | - |
3119 | - def connect_after(*a): |
3120 | - pass |
3121 | |
3122 | === modified file 'tests/inlinecalculator.py' |
3123 | --- tests/inlinecalculator.py 2011-02-19 16:27:44 +0000 |
3124 | +++ tests/inlinecalculator.py 2011-06-04 21:27:03 +0000 |
3125 | @@ -1,18 +1,15 @@ |
3126 | - |
3127 | # -*- coding: utf-8 -*- |
3128 | |
3129 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
3130 | |
3131 | import tests |
3132 | -from tests import TestCase |
3133 | |
3134 | import zim.plugins |
3135 | from zim.config import ConfigDict |
3136 | |
3137 | |
3138 | -class TestPrintToBrowser(TestCase): |
3139 | - |
3140 | - slowTest = True |
3141 | +@tests.slowTest |
3142 | +class TestPrintToBrowser(tests.TestCase): |
3143 | |
3144 | def runTest(self): |
3145 | 'Test InlineCalculator plugin' |
3146 | @@ -90,7 +87,7 @@ |
3147 | ui_type = 'stub' |
3148 | |
3149 | def __init__(self): |
3150 | - self.notebook = tests.get_test_notebook() |
3151 | + self.notebook = tests.new_notebook() |
3152 | self.preferences = ConfigDict() |
3153 | self.uistate = ConfigDict() |
3154 | |
3155 | |
3156 | === modified file 'tests/notebook.py' |
3157 | --- tests/notebook.py 2011-02-19 16:27:44 +0000 |
3158 | +++ tests/notebook.py 2011-06-04 21:27:03 +0000 |
3159 | @@ -13,11 +13,13 @@ |
3160 | import zim.errors |
3161 | from zim.formats import ParseTree |
3162 | |
3163 | - |
3164 | +from zim import _get_default_or_only_notebook |
3165 | + # private, but want to check it anyway |
3166 | + |
3167 | + |
3168 | +@tests.slowTest |
3169 | class TestGetNotebook(tests.TestCase): |
3170 | |
3171 | - slowTest = True |
3172 | - |
3173 | def setUp(self): |
3174 | list = config_file('notebooks.list') |
3175 | file = list.file |
3176 | @@ -25,16 +27,16 @@ |
3177 | file.remove() |
3178 | |
3179 | def runTest(self): |
3180 | - root = Dir(tests.create_tmp_dir(u'notebook_TestGetNotebook_\u0421\u0430\u0439')) |
3181 | + root = Dir(self.create_tmp_dir(u'some_utf8_here_\u0421\u0430\u0439')) |
3182 | |
3183 | # Start empty - see this is no issue |
3184 | list = get_notebook_list() |
3185 | - self.assertTrue(isinstance(list, NotebookList)) |
3186 | - self.assertFalse(list) |
3187 | + self.assertTrue(isinstance(list, NotebookInfoList)) |
3188 | + self.assertTrue(len(list) == 0) |
3189 | |
3190 | nb, page = resolve_notebook('foo') |
3191 | self.assertTrue(nb is None) |
3192 | - nb = resolve_default_notebook() |
3193 | + nb = _get_default_or_only_notebook() |
3194 | self.assertTrue(nb is None) |
3195 | |
3196 | # Non-existing dir |
3197 | @@ -56,36 +58,45 @@ |
3198 | self.assertEqual(page, Path('foo:bar:baz')) |
3199 | |
3200 | # And put it in the list and resolve it by name |
3201 | - list.append(dir.uri) |
3202 | + list = get_notebook_list() |
3203 | + list.append(NotebookInfo(dir.uri, name='foo')) |
3204 | list.write() |
3205 | - list = get_notebook_list() |
3206 | self.assertTrue(len(list) == 1) |
3207 | + self.assertTrue(isinstance(list[0], NotebookInfo)) |
3208 | + |
3209 | + info = list.get_by_name('foo') |
3210 | + self.assertEqual(info.uri, dir.uri) |
3211 | + self.assertEqual(info.name, 'foo') |
3212 | + |
3213 | nb, page = resolve_notebook('foo') |
3214 | self.assertEqual(nb, dir) |
3215 | |
3216 | # Single notebook is automatically the default |
3217 | - nb = resolve_default_notebook() |
3218 | - self.assertEqual(nb, dir) |
3219 | + nb = _get_default_or_only_notebook() |
3220 | + self.assertEqual(nb, dir.uri) |
3221 | |
3222 | # But not anymore after adding second notebook |
3223 | - list.append('file:///foo/bar') |
3224 | + list = get_notebook_list() |
3225 | + list.append(NotebookInfo('file:///foo/bar')) |
3226 | list.write() |
3227 | - list = get_notebook_list() |
3228 | self.assertTrue(len(list) == 2) |
3229 | - self.assertEqual(list[:], [dir.uri, 'file:///foo/bar']) |
3230 | + self.assertEqual(list[:], |
3231 | + [NotebookInfo(dir.uri), NotebookInfo('file:///foo/bar')]) |
3232 | |
3233 | nb, page = resolve_notebook('foo') |
3234 | self.assertEqual(nb, dir) |
3235 | self.assertTrue(isinstance(get_notebook(nb), Notebook)) |
3236 | |
3237 | - nb = resolve_default_notebook() |
3238 | + nb = _get_default_or_only_notebook() |
3239 | self.assertTrue(nb is None) |
3240 | |
3241 | - list.default = 'file:///default/foo' |
3242 | + list = get_notebook_list() |
3243 | + list.set_default('file:///foo/bar') |
3244 | list.write() |
3245 | - list = get_notebook_list() |
3246 | - nb = resolve_default_notebook() |
3247 | - self.assertEqual(nb, Dir('/default/foo')) |
3248 | + nb = _get_default_or_only_notebook() |
3249 | + self.assertEqual(nb, Dir('/foo/bar').uri) |
3250 | + nb, p = resolve_notebook(nb) |
3251 | + self.assertEqual(nb, Dir('/foo/bar')) |
3252 | self.assertEqual(get_notebook(nb), None) |
3253 | |
3254 | # Check interwiki parsing |
3255 | @@ -97,22 +108,20 @@ |
3256 | |
3257 | # Check backward compatibility |
3258 | file = File('tests/data/notebook-list-old-format.list') |
3259 | - wanted = [Dir('~/Notes').uri, Dir('/home/user/code/zim.debug').uri, Dir('/home/user/Foo Bar').uri] |
3260 | - list = NotebookList(file) |
3261 | - self.assertEqual(list[:], wanted) |
3262 | - self.assertEqual(list.default, Dir('/home/user/code/zim.debug').uri) |
3263 | + list = NotebookInfoList(file) |
3264 | + self.assertEqual(list[:], [ |
3265 | + NotebookInfo(Dir(path).uri) for path in |
3266 | + ('~/Notes', '/home/user/code/zim.debug', '/home/user/Foo Bar') |
3267 | + ]) |
3268 | + self.assertEqual(list.default, |
3269 | + NotebookInfo(Dir('/home/user/code/zim.debug').uri) ) |
3270 | |
3271 | |
3272 | class TestNotebook(tests.TestCase): |
3273 | |
3274 | def setUp(self): |
3275 | - zim.errors.silence_signal_exception_context = True |
3276 | - if not hasattr(self, 'notebook'): |
3277 | - self.notebook = tests.get_test_notebook() |
3278 | - self.notebook.index.update() |
3279 | - |
3280 | - def tearDown(self): |
3281 | - zim.errors.silence_signal_exception_context = False |
3282 | + path = self.get_tmp_name() |
3283 | + self.notebook = tests.new_notebook(fakedir=path) |
3284 | |
3285 | def testAPI(self): |
3286 | '''Test various notebook methods''' |
3287 | @@ -246,6 +255,13 @@ |
3288 | ':AnotherNewPage:Foo:bar\n' |
3289 | '**bold** :AnotherNewPage\n' ) |
3290 | |
3291 | + |
3292 | + # Try trashing |
3293 | + try: |
3294 | + self.notebook.trash_page(Path('TrashMe')) |
3295 | + except TrashNotSupportedError: |
3296 | + print 'trashing not supported' |
3297 | + |
3298 | #~ print '\n==== DB ====' |
3299 | #~ self.notebook.index.ensure_update() |
3300 | #~ cursor = self.notebook.index.db.cursor() |
3301 | @@ -324,15 +340,15 @@ |
3302 | [[Dus:Ja|Grrr]] # relative link that needs updating on move, but not on rename - with name |
3303 | [[:Foo:Bar:Dus]] # Link that could be made relative, but isn't |
3304 | ''' |
3305 | - notebook, page = tests.get_test_page('Foo:Bar:Baz') |
3306 | + page = self.notebook.get_page(Path('Foo:Bar:Baz')) |
3307 | page.parse('wiki', text) |
3308 | - notebook._update_links_from(page, Path('Dus:Baz'), page, Path('Dus:Baz')) |
3309 | - self.assertEqualDiff(u''.join(page.dump('wiki')), wanted1) |
3310 | + self.notebook._update_links_from(page, Path('Dus:Baz'), page, Path('Dus:Baz')) |
3311 | + self.assertEqual(u''.join(page.dump('wiki')), wanted1) |
3312 | |
3313 | - notebook, page = tests.get_test_page('Dus:Bar') |
3314 | + page = self.notebook.get_page(Path('Dus:Bar')) |
3315 | page.parse('wiki', text) |
3316 | - notebook._update_links_from(page, Path('Dus:Baz'), page, Path('Dus:Baz')) |
3317 | - self.assertEqualDiff(u''.join(page.dump('wiki')), wanted2) |
3318 | + self.notebook._update_links_from(page, Path('Dus:Baz'), page, Path('Dus:Baz')) |
3319 | + self.assertEqual(u''.join(page.dump('wiki')), wanted2) |
3320 | |
3321 | # updating links to the page that was moved |
3322 | # moving from Dus:Baz to Foo:Bar:Baz or renaming to Dus:Bar - updating links in Dus:Ja |
3323 | @@ -366,15 +382,15 @@ |
3324 | [[Bar:Hmm]] # absolute link that needs updating |
3325 | [[Bar:Hmm:Ja]] # absolute link that needs updating |
3326 | ''' |
3327 | - notebook, page = tests.get_test_page('Dus:Ja') |
3328 | + page = self.notebook.get_page(Path('Dus:Ja')) |
3329 | page.parse('wiki', text) |
3330 | - notebook._update_links_in_page(page, Path('Dus:Baz'), Path('Foo:Bar:Baz')) |
3331 | - self.assertEqualDiff(u''.join(page.dump('wiki')), wanted1) |
3332 | + self.notebook._update_links_in_page(page, Path('Dus:Baz'), Path('Foo:Bar:Baz')) |
3333 | + self.assertEqual(u''.join(page.dump('wiki')), wanted1) |
3334 | |
3335 | - notebook, page = tests.get_test_page('Dus:Ja') |
3336 | + page = self.notebook.get_page(Path('Dus:Ja')) |
3337 | page.parse('wiki', text) |
3338 | - notebook._update_links_in_page(page, Path('Dus:Baz'), Path('Dus:Bar')) |
3339 | - self.assertEqualDiff(u''.join(page.dump('wiki')), wanted2) |
3340 | + self.notebook._update_links_in_page(page, Path('Dus:Baz'), Path('Dus:Bar')) |
3341 | + self.assertEqual(u''.join(page.dump('wiki')), wanted2) |
3342 | |
3343 | # now test actual move on full notebook |
3344 | def links(source, href): |
3345 | @@ -438,12 +454,12 @@ |
3346 | |
3347 | def testResolveFile(self): |
3348 | '''Test notebook.resolve_file()''' |
3349 | - dir = Dir(tests.create_tmp_dir('notebook_testResolveFile')) |
3350 | path = Path('Foo:Bar') |
3351 | - self.notebook.dir = dir |
3352 | - self.notebook.get_store(path).dir = dir |
3353 | + dir = self.notebook.dir |
3354 | self.notebook.config['Notebook']['document_root'] = './notebook_document_root' |
3355 | - doc_root = self.notebook.get_document_root() |
3356 | + self.notebook.do_properties_changed() # parse config |
3357 | + doc_root = self.notebook.document_root |
3358 | + self.assertEqual(doc_root, dir.subdir('notebook_document_root')) |
3359 | for link, wanted, cleaned in ( |
3360 | ('~/test.txt', File('~/test.txt'), '~/test.txt'), |
3361 | (r'~\test.txt', File('~/test.txt'), '~/test.txt'), |
3362 | @@ -451,6 +467,7 @@ |
3363 | ('file:/test.txt', File('file:///test.txt'), None), |
3364 | ('file://localhost/test.txt', File('file:///test.txt'), None), |
3365 | ('/test.txt', doc_root.file('test.txt'), '/test.txt'), |
3366 | + ('../../notebook_document_root/test.txt', doc_root.file('test.txt'), '/test.txt'), |
3367 | ('./test.txt', dir.file('Foo/Bar/test.txt'), './test.txt'), |
3368 | (r'.\test.txt', dir.file('Foo/Bar/test.txt'), './test.txt'), |
3369 | ('../test.txt', dir.file('Foo/test.txt'), '../test.txt'), |
3370 | @@ -468,6 +485,10 @@ |
3371 | # check relative path without Path |
3372 | self.assertEqual( |
3373 | self.notebook.relative_filepath(doc_root.file('foo.txt')), '/foo.txt') |
3374 | + self.assertEqual( |
3375 | + self.notebook.relative_filepath(dir.file('foo.txt')), './foo.txt') |
3376 | + |
3377 | + |
3378 | |
3379 | # def testResolveLink(self): |
3380 | # '''Test page.resolve_link()''' |
3381 | @@ -542,7 +563,7 @@ |
3382 | '''Test page object''' |
3383 | |
3384 | def setUp(self): |
3385 | - self.notebook = tests.get_test_notebook() |
3386 | + self.notebook = tests.new_notebook() |
3387 | |
3388 | def generator(self, name): |
3389 | return self.notebook.get_page(Path(name)) |
3390 | @@ -555,6 +576,7 @@ |
3391 | <zim-tree> |
3392 | <link href='foo:bar'>foo:bar</link> |
3393 | <link href='bar'>bar</link> |
3394 | +<tag name='baz'>@baz</tag> |
3395 | </zim-tree> |
3396 | ''' ) |
3397 | page = Page(Path('Foo')) |
3398 | @@ -567,6 +589,11 @@ |
3399 | ('page', 'bar', {}), |
3400 | ] ) |
3401 | |
3402 | + tags = list(page.get_tags()) |
3403 | + self.assertEqual(tags, [ |
3404 | + ('@baz', {'name': 'baz'}), |
3405 | + ]) |
3406 | + |
3407 | self.assertEqual(page.get_parsetree().tostring(), tree.tostring()) |
3408 | # ensure we didn't change the tree |
3409 | |
3410 | @@ -581,7 +608,7 @@ |
3411 | class TestIndexPage(tests.TestCase): |
3412 | |
3413 | def setUp(self): |
3414 | - self.notebook = tests.get_test_notebook() |
3415 | + self.notebook = tests.new_notebook() |
3416 | self.notebook.index.update() |
3417 | |
3418 | def runTest(self): |
3419 | |
3420 | === renamed file 'tests/coding.py' => 'tests/package.py' |
3421 | --- tests/coding.py 2011-02-14 20:22:50 +0000 |
3422 | +++ tests/package.py 2011-06-04 21:27:03 +0000 |
3423 | @@ -1,16 +1,44 @@ |
3424 | - |
3425 | -from tests import TestCase |
3426 | +# -*- coding: utf-8 -*- |
3427 | + |
3428 | +# Copyright 2011 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
3429 | + |
3430 | +# This module contains a number of meta test to check coding style |
3431 | +# and packaging |
3432 | + |
3433 | +import tests |
3434 | |
3435 | import os |
3436 | import copy |
3437 | - |
3438 | - |
3439 | -class TestCoding(TestCase): |
3440 | +import re |
3441 | + |
3442 | + |
3443 | +class TestCompileAll(tests.TestCase): |
3444 | + |
3445 | + def runTest(self): |
3446 | + '''Test if all modules compile''' |
3447 | + for file in tests.zim_pyfiles(): |
3448 | + module = file[:-3].replace('/', '.') |
3449 | + assert __import__(module) |
3450 | + |
3451 | + |
3452 | +@tests.slowTest |
3453 | +class TestNotebookUpgrade(tests.TestCase): |
3454 | + |
3455 | + def runTest(self): |
3456 | + '''Test if included notebooks are up to date''' |
3457 | + from zim.fs import Dir |
3458 | + from zim.notebook import get_notebook |
3459 | + for path in ('data/manual', 'HACKING'): |
3460 | + notebook = get_notebook(Dir(path)) |
3461 | + self.assertTrue(not notebook.needs_upgrade) |
3462 | + |
3463 | + |
3464 | +class TestCoding(tests.TestCase): |
3465 | '''This test case enforces some coding style items''' |
3466 | |
3467 | def __init__(self, *a): |
3468 | self._code_files = [] |
3469 | - TestCase.__init__(self, *a) |
3470 | + tests.TestCase.__init__(self, *a) |
3471 | |
3472 | def list_code(self): |
3473 | '''Return all python files as text''' |
3474 | @@ -23,16 +51,32 @@ |
3475 | self._code_files = [] |
3476 | for root in ('zim', 'tests'): |
3477 | for dir, dirs, files in os.walk(root): |
3478 | - if 'coding.py' in files: |
3479 | - files.remove('coding.py') # Skip this file itself |
3480 | for basename in files: |
3481 | if basename.endswith('.py'): |
3482 | file = dir + '/' + basename |
3483 | - #print 'READING', file |
3484 | + if file == 'tests/package.py': # skip ourselve |
3485 | + continue |
3486 | + #~ print 'READING', file |
3487 | fh = open(file) |
3488 | self._code_files.append((file, fh.read())) |
3489 | fh.close() |
3490 | |
3491 | + def testWrongDependencies(self): |
3492 | + '''Check clean dependencies''' |
3493 | + #~ for klass in ('gobject', 'gtk', 'gio'): # TODO get rid of gobject as well |
3494 | + for klass in ('gtk', 'gio'): |
3495 | + import_re = re.compile(r'^(import|from)\s+%s' % klass, re.M) |
3496 | + # only match global imports - allow import in limitted scope |
3497 | + for file, code in self.list_code(): |
3498 | + if file.startswith('zim/gui') \ |
3499 | + or file.startswith('zim/_lib/') \ |
3500 | + or file.startswith('zim/plugins/') \ |
3501 | + or file.startswith('tests/'): |
3502 | + continue # skip |
3503 | + match = import_re.search(code) |
3504 | + if match: print '>>>', match.group(0) |
3505 | + self.assertFalse(match, '%s imports %s, this is not allowed' % (file, klass)) |
3506 | + |
3507 | def testWrongMethog(self): |
3508 | '''Check for a couple of constructs to be avoided''' |
3509 | for file, code in self.list_code(): |
3510 | @@ -45,24 +89,24 @@ |
3511 | '''Check python 2.5 compatibility''' |
3512 | for file, code in self.list_code(): |
3513 | import_seen = False |
3514 | - in_comment = False |
3515 | - n = 0 |
3516 | + suspect = False |
3517 | for line in code.splitlines(): |
3518 | - n += 1 |
3519 | - line = line.lstrip() |
3520 | + line = line.strip() |
3521 | if line.startswith('from __future__ ') \ |
3522 | and 'with_statement' in line.split(): |
3523 | import_seen = True |
3524 | - elif in_comment: |
3525 | - if line.endswith("'''"): |
3526 | - in_comment = False |
3527 | - else: |
3528 | - pass |
3529 | - elif line.startswith("'''"): |
3530 | - if not line.endswith("'''"): |
3531 | - in_comment = True |
3532 | - else: |
3533 | - pass |
3534 | - elif line.startswith('with '): |
3535 | - self.assertTrue(import_seen, '%s missing with_statement import from __future__ ("with" seen on line %i)' % (file, n)) |
3536 | - |
3537 | + elif line.startswith('with') and line.endswith(':'): |
3538 | + suspect = True |
3539 | + |
3540 | + #~ if suspect: print file, 'uses "with" statement' |
3541 | + |
3542 | + if suspect and not import_seen: |
3543 | + # Need real parsing to avoid false positives |
3544 | + import tokenize |
3545 | + import StringIO |
3546 | + |
3547 | + for token in tokenize.generate_tokens(StringIO.StringIO(code).readline): |
3548 | + if token[0] == tokenize.NAME and token[1] == 'with': |
3549 | + lineno = token[2][0] |
3550 | + line = token[-1] |
3551 | + self.assertTrue(import_seen, '%s missing with_statement import from __future__ ("with" seen on line %i):\n%s' % (file, lineno, line)) |
3552 | |
3553 | === modified file 'tests/pageview.py' |
3554 | --- tests/pageview.py 2011-02-19 16:27:44 +0000 |
3555 | +++ tests/pageview.py 2011-06-04 21:27:03 +0000 |
3556 | @@ -4,8 +4,8 @@ |
3557 | |
3558 | from __future__ import with_statement |
3559 | |
3560 | -from tests import TestCase, LoggingFilter, MockObject, \ |
3561 | - get_test_data_page, get_test_page |
3562 | +import tests |
3563 | + |
3564 | |
3565 | from zim.fs import * |
3566 | from zim.formats import wiki, ParseTree |
3567 | @@ -14,7 +14,7 @@ |
3568 | from zim.config import ConfigDict |
3569 | |
3570 | |
3571 | -class FilterNoSuchImageWarning(LoggingFilter): |
3572 | +class FilterNoSuchImageWarning(tests.LoggingFilter): |
3573 | |
3574 | logger = 'zim.gui.pageview' |
3575 | message = 'No such image:' |
3576 | @@ -22,8 +22,8 @@ |
3577 | |
3578 | def get_tree(wikitext): |
3579 | tree = wiki.Parser().parse(wikitext) |
3580 | - notebook, page = get_test_page() |
3581 | - notebook.get_store(page).dir = Dir('/foo') # HACK |
3582 | + notebook = tests.new_notebook(fakedir='/foo') |
3583 | + page = notebook.get_page(Path('Foo')) |
3584 | tree.resolve_images(notebook, page) |
3585 | return tree |
3586 | |
3587 | @@ -37,11 +37,11 @@ |
3588 | return ParseTree(root) |
3589 | |
3590 | |
3591 | -class TestTextBuffer(TestCase): |
3592 | +class TestTextBuffer(tests.TestCase): |
3593 | |
3594 | def runTest(self): |
3595 | '''Test serialization and interaction of the page view textbuffer''' |
3596 | - wikitext = get_test_data_page('wiki', 'roundtrip') |
3597 | + wikitext = tests.WikiTestData.get('roundtrip') |
3598 | tree = get_tree(wikitext) |
3599 | buffer = TextBuffer() |
3600 | with FilterNoSuchImageWarning(): |
3601 | @@ -51,30 +51,30 @@ |
3602 | result1 = buffer.get_parsetree() |
3603 | #~ print tree.tostring() |
3604 | #~ print result1.tostring() |
3605 | - #~ self.assertEqualDiff(result1.tostring(), tree.tostring()) |
3606 | + #~ self.assertEqual(result1.tostring(), tree.tostring()) |
3607 | |
3608 | # Compare cooked tree after dumping back |
3609 | resulttext = u''.join(wiki.Dumper().dump(result1)) |
3610 | - self.assertEqualDiff(resulttext, wikitext) |
3611 | + self.assertEqual(resulttext, wikitext) |
3612 | |
3613 | # Compare we are stable when loading raw tree again |
3614 | raw = raw1.tostring() |
3615 | with FilterNoSuchImageWarning(): |
3616 | buffer.set_parsetree(raw1) |
3617 | - self.assertEqualDiff(raw1.tostring(), raw) |
3618 | + self.assertEqual(raw1.tostring(), raw) |
3619 | # If this fails, set_parsetree is modifying the tree |
3620 | raw2 = buffer.get_parsetree(raw=True) |
3621 | - self.assertEqualDiff(raw2.tostring(), raw) |
3622 | + self.assertEqual(raw2.tostring(), raw) |
3623 | # Actual cooked roundtrip test |
3624 | |
3625 | # Compare we are stable when loading cooked tree again |
3626 | cooked = result1.tostring() |
3627 | with FilterNoSuchImageWarning(): |
3628 | buffer.set_parsetree(result1) |
3629 | - self.assertEqualDiff(result1.tostring(), cooked) |
3630 | + self.assertEqual(result1.tostring(), cooked) |
3631 | # If this fails, set_parsetree is modifying the tree |
3632 | result2 = buffer.get_parsetree() |
3633 | - self.assertEqualDiff(result2.tostring(), cooked) |
3634 | + self.assertEqual(result2.tostring(), cooked) |
3635 | # Actual cooked roundtrip test |
3636 | |
3637 | # Test 'raw' really preserves "errors" |
3638 | @@ -101,7 +101,7 @@ |
3639 | |
3640 | rawtree = buffer.get_parsetree(raw=True) |
3641 | self.assertFalse(buffer.get_modified()) |
3642 | - self.assertEqualDiff(rawtree.tostring(), input) |
3643 | + self.assertEqual(rawtree.tostring(), input) |
3644 | |
3645 | # Test errors are cleaned up correctly |
3646 | wanted = '''\ |
3647 | @@ -124,7 +124,7 @@ |
3648 | <li bullet="*" indent="0">Foo</li><li bullet="*" indent="0">Bar</li></zim-tree>''' |
3649 | tree = buffer.get_parsetree() |
3650 | self.assertFalse(buffer.get_modified()) |
3651 | - self.assertEqualDiff(tree.tostring(), wanted) |
3652 | + self.assertEqual(tree.tostring(), wanted) |
3653 | |
3654 | # Test pasting some simple text |
3655 | buffer.set_parsetree(tree) # reset without errors |
3656 | @@ -157,7 +157,7 @@ |
3657 | buffer.insert_parsetree(iter, pastetree, interactive=True) |
3658 | tree = buffer.get_parsetree() |
3659 | self.assertTrue(buffer.get_modified()) |
3660 | - self.assertEqualDiff(tree.tostring(), wanted) |
3661 | + self.assertEqual(tree.tostring(), wanted) |
3662 | |
3663 | # Now paste list halfway and see result is OK |
3664 | # because of the bullets pasting should go to a new line |
3665 | @@ -192,7 +192,7 @@ |
3666 | buffer.insert_parsetree(iter, pastetree, interactive=True) |
3667 | tree = buffer.get_parsetree() |
3668 | self.assertTrue(buffer.get_modified()) |
3669 | - self.assertEqualDiff(tree.tostring(), wanted) |
3670 | + self.assertEqual(tree.tostring(), wanted) |
3671 | |
3672 | # Test sanity for editing "errors" |
3673 | input = '''\ |
3674 | @@ -213,7 +213,7 @@ |
3675 | #print buffer.get_parsetree(raw=True).tostring() |
3676 | #print buffer.get_parsetree().tostring() |
3677 | tree = buffer.get_parsetree() |
3678 | - self.assertEqualDiff(tree.tostring(), wanted) |
3679 | + self.assertEqual(tree.tostring(), wanted) |
3680 | |
3681 | # Strange bug let to second bullet disappearing in this case |
3682 | input = '''\ |
3683 | @@ -231,7 +231,7 @@ |
3684 | #~ print buffer.get_parsetree(raw=True).tostring() |
3685 | #~ print buffer.get_parsetree().tostring() |
3686 | tree = buffer.get_parsetree() |
3687 | - self.assertEqualDiff(tree.tostring(), input) |
3688 | + self.assertEqual(tree.tostring(), input) |
3689 | |
3690 | # Check how robust we are for placeholder utf8 character |
3691 | buffer = TextBuffer() |
3692 | @@ -240,7 +240,7 @@ |
3693 | <?xml version='1.0' encoding='utf-8'?> |
3694 | <zim-tree>foo bar</zim-tree>''' |
3695 | tree = buffer.get_parsetree() |
3696 | - self.assertEqualDiff(tree.tostring(), wanted) |
3697 | + self.assertEqual(tree.tostring(), wanted) |
3698 | |
3699 | # Test merge lines logic on delete |
3700 | input = '''\ |
3701 | @@ -263,7 +263,7 @@ |
3702 | tree = get_tree_from_xml(input) |
3703 | buffer.set_parsetree(tree) |
3704 | tree = buffer.get_parsetree() |
3705 | - self.assertEqualDiff(tree.tostring(), input) |
3706 | + self.assertEqual(tree.tostring(), input) |
3707 | |
3708 | iter = buffer.get_iter_at_line(2) # before h2 |
3709 | bound = iter.copy() |
3710 | @@ -283,7 +283,7 @@ |
3711 | #~ print buffer.get_parsetree(raw=True).tostring() |
3712 | #~ print buffer.get_parsetree().tostring() |
3713 | tree = buffer.get_parsetree() |
3714 | - self.assertEqualDiff(tree.tostring(), wanted) |
3715 | + self.assertEqual(tree.tostring(), wanted) |
3716 | |
3717 | |
3718 | |
3719 | @@ -303,7 +303,7 @@ |
3720 | tree = get_tree_from_xml(input) |
3721 | buffer.set_parsetree(tree) |
3722 | tree = buffer.get_parsetree(raw=True) |
3723 | - self.assertEqualDiff(tree.tostring(), input) # just a sanity check |
3724 | + self.assertEqual(tree.tostring(), input) # just a sanity check |
3725 | |
3726 | wanted = '''\ |
3727 | <?xml version='1.0' encoding='utf-8'?> |
3728 | @@ -325,7 +325,7 @@ |
3729 | buffer.toggle_checkbox_for_cursor_or_selection(XCHECKED_BOX) |
3730 | # Like <Shift><F12> on first list item line |
3731 | tree = buffer.get_parsetree(raw=True) |
3732 | - self.assertEqualDiff(tree.tostring(), wanted) |
3733 | + self.assertEqual(tree.tostring(), wanted) |
3734 | |
3735 | wanted = '''\ |
3736 | <?xml version='1.0' encoding='utf-8'?> |
3737 | @@ -346,7 +346,7 @@ |
3738 | buffer.toggle_checkbox_for_cursor_or_selection(CHECKED_BOX, recursive=True) |
3739 | # Like keypress would trigger while selection present |
3740 | tree = buffer.get_parsetree(raw=True) |
3741 | - self.assertEqualDiff(tree.tostring(), wanted) |
3742 | + self.assertEqual(tree.tostring(), wanted) |
3743 | |
3744 | |
3745 | # Test deleting checkbox and undo / redo does not mess up indenting etc |
3746 | @@ -364,24 +364,24 @@ |
3747 | end = buffer.get_iter_at_line(7) # Baz (before checkbox !) |
3748 | buffer.delete(start, end) |
3749 | tree = buffer.get_parsetree(raw=True) |
3750 | - self.assertEqualDiff(tree.tostring(), wanted) |
3751 | + self.assertEqual(tree.tostring(), wanted) |
3752 | |
3753 | undomanager.undo() |
3754 | tree = buffer.get_parsetree(raw=True) |
3755 | - self.assertEqualDiff(tree.tostring(), previous) |
3756 | + self.assertEqual(tree.tostring(), previous) |
3757 | |
3758 | undomanager.redo() |
3759 | tree = buffer.get_parsetree(raw=True) |
3760 | - self.assertEqualDiff(tree.tostring(), wanted) |
3761 | - |
3762 | - |
3763 | -class TestUndoStackManager(TestCase): |
3764 | + self.assertEqual(tree.tostring(), wanted) |
3765 | + |
3766 | + |
3767 | +class TestUndoStackManager(tests.TestCase): |
3768 | |
3769 | def runTest(self): |
3770 | '''Test the undo/redo functionality''' |
3771 | buffer = TextBuffer() |
3772 | undomanager = UndoStackManager(buffer) |
3773 | - wikitext = get_test_data_page('wiki', 'roundtrip') |
3774 | + wikitext = tests.WikiTestData.get('roundtrip') |
3775 | tree = get_tree(wikitext) |
3776 | |
3777 | with FilterNoSuchImageWarning(): |
3778 | @@ -419,7 +419,7 @@ |
3779 | _ = buffer.get_parsetree() # just check for no warnings |
3780 | |
3781 | emptytree = buffer.get_parsetree(raw=True) |
3782 | - self.assertEqualDiff(emptytree.tostring(), |
3783 | + self.assertEqual(emptytree.tostring(), |
3784 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree raw=\"True\" />") |
3785 | |
3786 | with FilterNoSuchImageWarning(): |
3787 | @@ -427,13 +427,13 @@ |
3788 | _ = buffer.get_parsetree() # just check for no warnings |
3789 | |
3790 | buffertree2 = buffer.get_parsetree(raw=True) |
3791 | - self.assertEqualDiff(buffertree2.tostring(), buffertree1.tostring()) |
3792 | + self.assertEqual(buffertree2.tostring(), buffertree1.tostring()) |
3793 | |
3794 | while undomanager.undo(): |
3795 | continue |
3796 | |
3797 | emptytree = buffer.get_parsetree(raw=True) |
3798 | - self.assertEqualDiff(emptytree.tostring(), |
3799 | + self.assertEqual(emptytree.tostring(), |
3800 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree raw=\"True\" />") |
3801 | |
3802 | buffer.clear() |
3803 | @@ -450,7 +450,7 @@ |
3804 | self.assertTrue(len(undomanager.stack) == 5) # 3 words, 2 spaces |
3805 | for group in undomanager.stack: |
3806 | self.assertTrue(len(group) == 1) # merge was sucessfull |
3807 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3808 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3809 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo barr baz</zim-tree>") |
3810 | |
3811 | for wanted in ( |
3812 | @@ -461,11 +461,11 @@ |
3813 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree />" |
3814 | ): |
3815 | undomanager.undo() |
3816 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), wanted) |
3817 | + self.assertEqual(buffer.get_parsetree().tostring(), wanted) |
3818 | |
3819 | while undomanager.redo(): |
3820 | continue |
3821 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3822 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3823 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo barr baz</zim-tree>") |
3824 | |
3825 | # test other actions |
3826 | @@ -473,29 +473,29 @@ |
3827 | buffer.place_cursor(iter) |
3828 | buffer.select_word() |
3829 | buffer.toggle_textstyle('strong', interactive=True) |
3830 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3831 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3832 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo <strong>barr</strong> baz</zim-tree>") |
3833 | |
3834 | undomanager.undo() |
3835 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3836 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3837 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo barr baz</zim-tree>") |
3838 | |
3839 | undomanager.redo() |
3840 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3841 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3842 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo <strong>barr</strong> baz</zim-tree>") |
3843 | |
3844 | start, end = map(buffer.get_iter_at_offset, (5, 10)) |
3845 | with buffer.user_action: |
3846 | buffer.delete(start, end) |
3847 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3848 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3849 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo baz</zim-tree>") |
3850 | |
3851 | undomanager.undo() |
3852 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3853 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3854 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo <strong>barr</strong> baz</zim-tree>") |
3855 | |
3856 | undomanager.redo() |
3857 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3858 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3859 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo baz</zim-tree>") |
3860 | |
3861 | # test folding |
3862 | @@ -504,25 +504,25 @@ |
3863 | undomanager.undo() |
3864 | undomanager.undo() |
3865 | |
3866 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3867 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3868 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo barr</zim-tree>") |
3869 | |
3870 | with buffer.user_action: |
3871 | buffer.insert_at_cursor(' ') |
3872 | |
3873 | undomanager.undo() |
3874 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3875 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3876 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo barr</zim-tree>") |
3877 | |
3878 | undomanager.undo() # here we undo fold of 4 undos above |
3879 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3880 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3881 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo baz</zim-tree>") |
3882 | undomanager.undo() |
3883 | - self.assertEqualDiff(buffer.get_parsetree().tostring(), |
3884 | + self.assertEqual(buffer.get_parsetree().tostring(), |
3885 | "<?xml version='1.0' encoding='utf-8'?>\n<zim-tree>fooo <strong>barr</strong> baz</zim-tree>") |
3886 | |
3887 | |
3888 | -class TestFind(TestCase): |
3889 | +class TestFind(tests.TestCase): |
3890 | |
3891 | def runTest(self): |
3892 | buffer = TextBuffer() |
3893 | @@ -623,7 +623,7 @@ |
3894 | FooBaz Foo Bar |
3895 | foo Bar Baz Foo |
3896 | ''' |
3897 | - self.assertEqualDiff(text, wanted) |
3898 | + self.assertEqual(text, wanted) |
3899 | |
3900 | finder.replace_all('dus*\\1*') |
3901 | bounds = buffer.get_bounds() |
3902 | @@ -633,11 +633,11 @@ |
3903 | dus*Baz* dus** Bar |
3904 | dus** Bar Baz dus** |
3905 | ''' |
3906 | - self.assertEqualDiff(text, wanted) |
3907 | + self.assertEqual(text, wanted) |
3908 | self.assertEqual(buffer.get_insert_iter().get_offset(), 6) |
3909 | |
3910 | |
3911 | -class TestLists(TestCase): |
3912 | +class TestLists(tests.TestCase): |
3913 | |
3914 | def runTest(self): |
3915 | '''Test interaction for lists''' |
3916 | @@ -658,7 +658,7 @@ |
3917 | tree = get_tree_from_xml(input) |
3918 | buffer.set_parsetree(tree) |
3919 | tree = buffer.get_parsetree(raw=True) |
3920 | - self.assertEqualDiff(tree.tostring(), input) # just a sanity check |
3921 | + self.assertEqual(tree.tostring(), input) # just a sanity check |
3922 | |
3923 | undomanager = UndoStackManager(buffer) |
3924 | |
3925 | @@ -703,7 +703,7 @@ |
3926 | Tja |
3927 | </zim-tree>''' |
3928 | tree = buffer.get_parsetree(raw=True) |
3929 | - self.assertEqualDiff(tree.tostring(), wanted) |
3930 | + self.assertEqual(tree.tostring(), wanted) |
3931 | |
3932 | iter = buffer.get_iter_at_line(7) # Baz |
3933 | row, list = TextBufferList.new_from_iter(buffer, iter) |
3934 | @@ -728,7 +728,7 @@ |
3935 | Tja |
3936 | </zim-tree>''' |
3937 | tree = buffer.get_parsetree(raw=True) |
3938 | - self.assertEqualDiff(tree.tostring(), wanted) |
3939 | + self.assertEqual(tree.tostring(), wanted) |
3940 | |
3941 | for line in (2, 5, 6): # Bar, Bar 2 & Bar 3 |
3942 | iter = buffer.get_iter_at_line(line) |
3943 | @@ -737,28 +737,28 @@ |
3944 | self.assertTrue(list.unindent(row)) |
3945 | |
3946 | tree = buffer.get_parsetree(raw=True) |
3947 | - self.assertEqualDiff(tree.tostring(), input) |
3948 | + self.assertEqual(tree.tostring(), input) |
3949 | |
3950 | # Test undo / redo for indenting and lists |
3951 | for i in range(3): |
3952 | self.assertTrue(undomanager.undo()) |
3953 | tree = buffer.get_parsetree(raw=True) |
3954 | - self.assertEqualDiff(tree.tostring(), wanted) |
3955 | + self.assertEqual(tree.tostring(), wanted) |
3956 | |
3957 | while undomanager.undo(): |
3958 | pass |
3959 | tree = buffer.get_parsetree(raw=True) |
3960 | - self.assertEqualDiff(tree.tostring(), input) |
3961 | + self.assertEqual(tree.tostring(), input) |
3962 | |
3963 | while undomanager.redo(): |
3964 | pass |
3965 | tree = buffer.get_parsetree(raw=True) |
3966 | - self.assertEqualDiff(tree.tostring(), input) |
3967 | + self.assertEqual(tree.tostring(), input) |
3968 | |
3969 | for i in range(3): |
3970 | self.assertTrue(undomanager.undo()) |
3971 | tree = buffer.get_parsetree(raw=True) |
3972 | - self.assertEqualDiff(tree.tostring(), wanted) |
3973 | + self.assertEqual(tree.tostring(), wanted) |
3974 | |
3975 | |
3976 | # Exercize recursive checkbox lists |
3977 | @@ -777,7 +777,7 @@ |
3978 | tree = get_tree_from_xml(input) |
3979 | buffer.set_parsetree(tree) |
3980 | tree = buffer.get_parsetree(raw=True) |
3981 | - self.assertEqualDiff(tree.tostring(), input) # just a sanity check |
3982 | + self.assertEqual(tree.tostring(), input) # just a sanity check |
3983 | |
3984 | undomanager = UndoStackManager(buffer) |
3985 | |
3986 | @@ -798,7 +798,7 @@ |
3987 | Tja |
3988 | </zim-tree>''' |
3989 | tree = buffer.get_parsetree(raw=True) |
3990 | - self.assertEqualDiff(tree.tostring(), wanted) |
3991 | + self.assertEqual(tree.tostring(), wanted) |
3992 | |
3993 | list.set_bullet(row, UNCHECKED_BOX) |
3994 | row = list.get_row_at_line(3) # Bar 1 |
3995 | @@ -818,7 +818,7 @@ |
3996 | Tja |
3997 | </zim-tree>''' |
3998 | tree = buffer.get_parsetree(raw=True) |
3999 | - self.assertEqualDiff(tree.tostring(), wanted) |
4000 | + self.assertEqual(tree.tostring(), wanted) |
4001 | |
4002 | row = list.get_row_at_line(5) # Bar 2 |
4003 | list.set_bullet(row, CHECKED_BOX) |
4004 | @@ -835,7 +835,7 @@ |
4005 | Tja |
4006 | </zim-tree>''' |
4007 | tree = buffer.get_parsetree(raw=True) |
4008 | - self.assertEqualDiff(tree.tostring(), wanted) |
4009 | + self.assertEqual(tree.tostring(), wanted) |
4010 | |
4011 | row = list.get_row_at_line(4) # Bar 1.1 |
4012 | list.set_bullet(row, UNCHECKED_BOX) |
4013 | @@ -852,7 +852,7 @@ |
4014 | Tja |
4015 | </zim-tree>''' |
4016 | tree = buffer.get_parsetree(raw=True) |
4017 | - self.assertEqualDiff(tree.tostring(), wanted) |
4018 | + self.assertEqual(tree.tostring(), wanted) |
4019 | |
4020 | wantedpre1 = wanted |
4021 | row = list.get_row_at_line(4) # Bar 1.1 |
4022 | @@ -870,7 +870,7 @@ |
4023 | Tja |
4024 | </zim-tree>''' |
4025 | tree = buffer.get_parsetree(raw=True) |
4026 | - self.assertEqualDiff(tree.tostring(), wanted) |
4027 | + self.assertEqual(tree.tostring(), wanted) |
4028 | |
4029 | # Test indenting / unindenting the whole list |
4030 | wantedpre = wanted |
4031 | @@ -889,32 +889,32 @@ |
4032 | Tja |
4033 | </zim-tree>''' |
4034 | tree = buffer.get_parsetree(raw=True) |
4035 | - self.assertEqualDiff(tree.tostring(), wanted) |
4036 | + self.assertEqual(tree.tostring(), wanted) |
4037 | |
4038 | list.unindent(row) |
4039 | tree = buffer.get_parsetree(raw=True) |
4040 | - self.assertEqualDiff(tree.tostring(), wantedpre) |
4041 | + self.assertEqual(tree.tostring(), wantedpre) |
4042 | |
4043 | # Test undo / redo for indenting and lists |
4044 | for xml in (wanted, wantedpre, wantedpre1): |
4045 | self.assertTrue(undomanager.undo()) |
4046 | tree = buffer.get_parsetree(raw=True) |
4047 | - self.assertEqualDiff(tree.tostring(), xml) |
4048 | + self.assertEqual(tree.tostring(), xml) |
4049 | |
4050 | for xml in (wantedpre, wanted, wantedpre): |
4051 | self.assertTrue(undomanager.redo()) |
4052 | tree = buffer.get_parsetree(raw=True) |
4053 | - self.assertEqualDiff(tree.tostring(), xml) |
4054 | + self.assertEqual(tree.tostring(), xml) |
4055 | |
4056 | while undomanager.undo(): |
4057 | pass |
4058 | tree = buffer.get_parsetree(raw=True) |
4059 | - self.assertEqualDiff(tree.tostring(), input) |
4060 | + self.assertEqual(tree.tostring(), input) |
4061 | |
4062 | while undomanager.redo(): |
4063 | pass |
4064 | tree = buffer.get_parsetree(raw=True) |
4065 | - self.assertEqualDiff(tree.tostring(), wantedpre) |
4066 | + self.assertEqual(tree.tostring(), wantedpre) |
4067 | |
4068 | |
4069 | def press(widget, sequence): |
4070 | @@ -940,7 +940,7 @@ |
4071 | widget.emit('key-press-event', event) |
4072 | |
4073 | |
4074 | -class TestTextView(TestCase): |
4075 | +class TestTextView(tests.TestCase): |
4076 | |
4077 | def setUp(self): |
4078 | # Initialize default preferences from module |
4079 | @@ -974,7 +974,7 @@ |
4080 | <zim-tree raw="True">aaa |
4081 | <li bullet="*" indent="0"> foo</li></zim-tree>''' |
4082 | tree = buffer.get_parsetree(raw=True) |
4083 | - self.assertEqualDiff(tree.tostring(), wanted) |
4084 | + self.assertEqual(tree.tostring(), wanted) |
4085 | |
4086 | press(view, '\n') |
4087 | wanted = '''\ |
4088 | @@ -984,7 +984,7 @@ |
4089 | <li bullet="*" indent="0"> </li></zim-tree>''' |
4090 | tree = buffer.get_parsetree(raw=True) |
4091 | start, end = buffer.get_bounds() |
4092 | - self.assertEqualDiff(tree.tostring(), wanted) |
4093 | + self.assertEqual(tree.tostring(), wanted) |
4094 | |
4095 | press(view, '\tduss') |
4096 | wanted = '''\ |
4097 | @@ -993,7 +993,7 @@ |
4098 | <li bullet="*" indent="0"> foo</li> |
4099 | <li bullet="*" indent="1"> duss</li></zim-tree>''' |
4100 | tree = buffer.get_parsetree(raw=True) |
4101 | - self.assertEqualDiff(tree.tostring(), wanted) |
4102 | + self.assertEqual(tree.tostring(), wanted) |
4103 | |
4104 | press(view, '\n') |
4105 | wanted = '''\ |
4106 | @@ -1003,7 +1003,7 @@ |
4107 | <li bullet="*" indent="1"> duss</li> |
4108 | <li bullet="*" indent="1"> </li></zim-tree>''' |
4109 | tree = buffer.get_parsetree(raw=True) |
4110 | - self.assertEqualDiff(tree.tostring(), wanted) |
4111 | + self.assertEqual(tree.tostring(), wanted) |
4112 | |
4113 | press(view, 'CamelCase\n') |
4114 | wanted = '''\ |
4115 | @@ -1014,7 +1014,7 @@ |
4116 | <li bullet="*" indent="1"> <link href="CamelCase">CamelCase</link></li> |
4117 | <li bullet="*" indent="1"> </li></zim-tree>''' |
4118 | tree = buffer.get_parsetree(raw=True) |
4119 | - self.assertEqualDiff(tree.tostring(), wanted) |
4120 | + self.assertEqual(tree.tostring(), wanted) |
4121 | |
4122 | press(view, '\n') |
4123 | wanted = '''\ |
4124 | @@ -1026,7 +1026,7 @@ |
4125 | |
4126 | </zim-tree>''' |
4127 | tree = buffer.get_parsetree(raw=True) |
4128 | - self.assertEqualDiff(tree.tostring(), wanted) |
4129 | + self.assertEqual(tree.tostring(), wanted) |
4130 | |
4131 | # selection + * to toggle bullets |
4132 | start = buffer.get_iter_at_line(1) # before foo |
4133 | @@ -1042,7 +1042,7 @@ |
4134 | </div> |
4135 | </zim-tree>''' |
4136 | tree = buffer.get_parsetree(raw=True) |
4137 | - self.assertEqualDiff(tree.tostring(), wanted) |
4138 | + self.assertEqual(tree.tostring(), wanted) |
4139 | |
4140 | start = buffer.get_iter_at_line(1) # before foo |
4141 | end = buffer.get_iter_at_line(4) # empty line ! |
4142 | @@ -1057,7 +1057,7 @@ |
4143 | |
4144 | </zim-tree>''' |
4145 | tree = buffer.get_parsetree(raw=True) |
4146 | - self.assertEqualDiff(tree.tostring(), wanted) |
4147 | + self.assertEqual(tree.tostring(), wanted) |
4148 | |
4149 | iter = buffer.get_iter_at_line(1) |
4150 | iter.forward_to_line_end() # behind "foo" |
4151 | @@ -1073,7 +1073,7 @@ |
4152 | |
4153 | </zim-tree>''' |
4154 | tree = buffer.get_parsetree(raw=True) |
4155 | - self.assertEqualDiff(tree.tostring(), wanted) |
4156 | + self.assertEqual(tree.tostring(), wanted) |
4157 | |
4158 | |
4159 | |
4160 | @@ -1089,11 +1089,11 @@ |
4161 | |
4162 | </zim-tree>''' |
4163 | tree = buffer.get_parsetree(raw=True) |
4164 | - self.assertEqualDiff(tree.tostring(), wanted) |
4165 | + self.assertEqual(tree.tostring(), wanted) |
4166 | |
4167 | press(view, (KEYVALS_LEFT_TAB[0],)) # Check <Shift><Tab> does not fall through to Tab when indent fails |
4168 | tree = buffer.get_parsetree(raw=True) |
4169 | - self.assertEqualDiff(tree.tostring(), wanted) |
4170 | + self.assertEqual(tree.tostring(), wanted) |
4171 | |
4172 | press(view, (KEYVALS_BACKSPACE[0],)) # delete bullet at once |
4173 | wanted = '''\ |
4174 | @@ -1106,7 +1106,7 @@ |
4175 | |
4176 | </zim-tree>''' |
4177 | tree = buffer.get_parsetree(raw=True) |
4178 | - self.assertEqualDiff(tree.tostring(), wanted) |
4179 | + self.assertEqual(tree.tostring(), wanted) |
4180 | |
4181 | # TODO: this test case fails, even though it works when I try it interactively !? |
4182 | #~ press(view, (KEYVALS_BACKSPACE[0],)) # remove newline |
4183 | @@ -1119,7 +1119,7 @@ |
4184 | #~ |
4185 | #~ </zim-tree>''' |
4186 | #~ tree = buffer.get_parsetree(raw=True) |
4187 | - #~ self.assertEqualDiff(tree.tostring(), wanted) |
4188 | + #~ self.assertEqual(tree.tostring(), wanted) |
4189 | |
4190 | # TODO more unindenting ? |
4191 | # TODO checkboxes |
4192 | @@ -1127,15 +1127,15 @@ |
4193 | # TODO enter on link, before link, after link |
4194 | |
4195 | |
4196 | -class TestPageView(TestCase): |
4197 | +class TestPageView(tests.TestCase): |
4198 | |
4199 | def runTest(self): |
4200 | - PageView.actiongroup = MockObject() # use class attribute to fake ui init |
4201 | - PageView.actiongroup.mock_method('get_action', MockObject()) |
4202 | + PageView.actiongroup = tests.MockObject() # use class attribute to fake ui init |
4203 | + PageView.actiongroup.mock_method('get_action', tests.MockObject()) |
4204 | |
4205 | ui = MockUI() |
4206 | - ui.uimanager = MockObject() |
4207 | - ui.uimanager.mock_method('get_accel_group', MockObject()) |
4208 | + ui.uimanager = tests.MockObject() |
4209 | + ui.uimanager.mock_method('get_accel_group', tests.MockObject()) |
4210 | |
4211 | pageview = PageView(ui) |
4212 | buffer = pageview.view.get_buffer() |
4213 | @@ -1152,7 +1152,7 @@ |
4214 | # TODO much more here |
4215 | |
4216 | |
4217 | -class TestPageviewDialogs(TestCase): |
4218 | +class TestPageviewDialogs(tests.TestCase): |
4219 | |
4220 | def runTest(self): |
4221 | '''Test input/output of various pageview dialogs''' |
4222 | @@ -1204,11 +1204,13 @@ |
4223 | self.assertEqual(dialog.form['height'], 24) |
4224 | dialog.assert_response_ok() |
4225 | iter = buffer.get_iter_at_offset(0) |
4226 | - self.assertEqual(buffer.get_image_data(iter), { |
4227 | + imagedata = buffer.get_image_data(iter) |
4228 | + self.assertEqual(imagedata, { |
4229 | 'src': './data/zim.png', # preserve relative path |
4230 | '_src_file': file, |
4231 | 'height': 24, |
4232 | }) |
4233 | + self.assertEqual(type(imagedata['height']).__name__, 'int') |
4234 | |
4235 | ## Insert text from file dialog |
4236 | ui = MockUI() |
4237 | @@ -1220,9 +1222,9 @@ |
4238 | |
4239 | ## Insert Link dialog |
4240 | ui = MockUI() |
4241 | - ui.notebook.index = MockObject() |
4242 | + ui.notebook.index = tests.MockObject() |
4243 | ui.notebook.index.mock_method('list_pages', []) |
4244 | - pageview = MockObject() |
4245 | + pageview = tests.MockObject() |
4246 | pageview.page = Path('Test:foo:bar') |
4247 | textview = TextView({}) |
4248 | pageview.view = textview |
4249 | @@ -1252,25 +1254,27 @@ |
4250 | ''') |
4251 | |
4252 | ## Word Count dialog |
4253 | - pageview = MockObject() |
4254 | + pageview = tests.MockObject() |
4255 | pageview.view = textview |
4256 | pageview.ui = MockUI() |
4257 | dialog = WordCountDialog(pageview) |
4258 | dialog.destroy() # nothing to test really |
4259 | |
4260 | |
4261 | -class MockUI(MockObject): |
4262 | +class MockUI(tests.MockObject): |
4263 | |
4264 | def __init__(self): |
4265 | - MockObject.__init__(self) |
4266 | + tests.MockObject.__init__(self) |
4267 | self.mainwindow = None |
4268 | - self.notebook = MockObject() |
4269 | + self.notebook = tests.MockObject() |
4270 | self.preferences = ConfigDict() |
4271 | |
4272 | def register_preferences(self, section, list): |
4273 | - for key, type, category, label, default in list: |
4274 | + for p in list: |
4275 | + key = p[0] |
4276 | + default = p[4] |
4277 | self.preferences[section][key] = default |
4278 | |
4279 | |
4280 | -class MockBuffer(MockObject): |
4281 | +class MockBuffer(tests.MockObject): |
4282 | pass |
4283 | |
4284 | === modified file 'tests/parsing.py' |
4285 | --- tests/parsing.py 2011-02-19 16:27:44 +0000 |
4286 | +++ tests/parsing.py 2011-06-04 21:27:03 +0000 |
4287 | @@ -88,7 +88,7 @@ |
4288 | def testLinkType(self): |
4289 | '''Test link_type()''' |
4290 | for href, type in ( |
4291 | - ('zim+file://foo/bar?dus.txt', 'zim-notebook'), |
4292 | + ('zim+file://foo/bar?dus.txt', 'notebook'), |
4293 | ('file://foo/bar', 'file'), |
4294 | ('http://foo/bar', 'http'), |
4295 | ('http://192.168.168.100', 'http'), |
4296 | |
4297 | === modified file 'tests/plugins.py' |
4298 | --- tests/plugins.py 2011-02-19 16:27:44 +0000 |
4299 | +++ tests/plugins.py 2011-06-04 21:27:03 +0000 |
4300 | @@ -2,7 +2,7 @@ |
4301 | |
4302 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
4303 | |
4304 | -from tests import TestCase, get_test_notebook |
4305 | +import tests |
4306 | |
4307 | import os |
4308 | |
4309 | @@ -14,7 +14,7 @@ |
4310 | zim.plugins.__path__ = [os.path.abspath('./zim/plugins')] # set back default search path |
4311 | |
4312 | |
4313 | -class testPlugins(TestCase): |
4314 | +class testPlugins(tests.TestCase): |
4315 | '''FIXME''' |
4316 | |
4317 | def testListAll(self): |
4318 | @@ -35,20 +35,23 @@ |
4319 | |
4320 | # test dependencies data |
4321 | dep = plugin.check_dependencies() |
4322 | + self.assertTrue(isinstance(dep,tuple)) |
4323 | + check, dep = dep |
4324 | + self.assertTrue(isinstance(check,bool)) |
4325 | self.assertTrue(isinstance(dep,list)) |
4326 | for i in range(len(dep)): |
4327 | self.assertTrue(isinstance(dep[i],tuple)) |
4328 | self.assertTrue(isinstance(dep[i][0],str)) |
4329 | self.assertTrue(isinstance(dep[i][1],bool)) |
4330 | + self.assertTrue(isinstance(dep[i][2],bool)) |
4331 | |
4332 | def testDefaulPlugins(self): |
4333 | '''Test loading default plugins''' |
4334 | # Note that we use parent interface class here, so plugins |
4335 | # will not really attach - just testing loading and prereq |
4336 | # checks are OK. |
4337 | - notebook = get_test_notebook() |
4338 | + notebook = tests.new_notebook() |
4339 | interface = zim.NotebookInterface(notebook) |
4340 | interface.uistate = zim.config.ConfigDict() |
4341 | interface.load_plugins() |
4342 | self.assertTrue(len(interface.plugins) > 3) |
4343 | - |
4344 | |
4345 | === modified file 'tests/printtobrowser.py' |
4346 | --- tests/printtobrowser.py 2011-02-19 16:27:44 +0000 |
4347 | +++ tests/printtobrowser.py 2011-06-04 21:27:03 +0000 |
4348 | @@ -1,18 +1,16 @@ |
4349 | - |
4350 | # -*- coding: utf-8 -*- |
4351 | |
4352 | # Copyright 2008 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
4353 | |
4354 | import tests |
4355 | -from tests import TestCase |
4356 | |
4357 | import zim.plugins |
4358 | from zim.notebook import Path |
4359 | from zim.config import ConfigDict |
4360 | |
4361 | -class TestPrintToBrowser(TestCase): |
4362 | |
4363 | - slowTest = True |
4364 | +@tests.slowTest |
4365 | +class TestPrintToBrowser(tests.TestCase): |
4366 | |
4367 | def runTest(self): |
4368 | 'Test PrintToBrowser plugin' |
4369 | @@ -30,11 +28,11 @@ |
4370 | ui_type = 'stub' |
4371 | |
4372 | def __init__(self): |
4373 | - self.notebook = tests.get_test_notebook() |
4374 | + self.notebook = tests.new_notebook() |
4375 | self.page = self.notebook.get_page(Path('Test:foo')) |
4376 | self.preferences = ConfigDict() |
4377 | self.uistate = ConfigDict() |
4378 | - |
4379 | + |
4380 | def connect(*a): pass |
4381 | |
4382 | def connect_after(*a): pass |
4383 | |
4384 | === modified file 'tests/search.py' |
4385 | --- tests/search.py 2010-03-15 17:29:15 +0000 |
4386 | +++ tests/search.py 2011-06-04 21:27:03 +0000 |
4387 | @@ -1,10 +1,13 @@ |
4388 | - |
4389 | -from tests import get_test_notebook, TestCase |
4390 | +# -*- coding: utf-8 -*- |
4391 | + |
4392 | +# Copyright 2011 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
4393 | + |
4394 | +import tests |
4395 | |
4396 | from zim.search import * |
4397 | from zim.notebook import Path |
4398 | |
4399 | -class TestSearchRegex(TestCase): |
4400 | +class TestSearchRegex(tests.TestCase): |
4401 | |
4402 | def runTest(self): |
4403 | '''Test regex compilation for search terms''' |
4404 | @@ -35,10 +38,10 @@ |
4405 | |
4406 | |
4407 | |
4408 | -class TestSearch(TestCase): |
4409 | +class TestSearch(tests.TestCase): |
4410 | |
4411 | def setUp(self): |
4412 | - self.notebook = get_test_notebook() |
4413 | + self.notebook = tests.new_notebook() |
4414 | |
4415 | def runTest(self): |
4416 | '''Test search API''' |
4417 | @@ -136,32 +139,33 @@ |
4418 | self.assertTrue(set(results.scores.keys()) == results) |
4419 | self.assertTrue(all(results.scores.values())) |
4420 | |
4421 | + query = Query('Namespace: "TODOList" fix') |
4422 | + self.assertTrue(query.root.operator == OPERATOR_AND) |
4423 | + self.assertEqual(query.root, [QueryTerm('namespace', 'TODOList'), QueryTerm('contentorname', 'fix')]) |
4424 | + results.search(query) |
4425 | + #~ print results |
4426 | + self.assertTrue(Path('TODOList:foo') in results) |
4427 | + |
4428 | + query = Query('Tag: tags') |
4429 | + self.assertTrue(query.root.operator == OPERATOR_AND) |
4430 | + self.assertEqual(query.root, [QueryTerm('tag', 'tags')]) |
4431 | + query = Query('@tags') |
4432 | + self.assertTrue(query.root.operator == OPERATOR_AND) |
4433 | + self.assertEqual(query.root, [QueryTerm('tag', 'tags')]) |
4434 | + results.search(query) |
4435 | + #~ print results |
4436 | + self.assertTrue(Path('Test:tags') in results and len(results) == 1) |
4437 | + |
4438 | # TODO test ContentOrName versus Content |
4439 | - # TODO test Name and Namespace |
4440 | - |
4441 | - |
4442 | -def get_files_notebook(name): |
4443 | - from tests import create_tmp_dir, get_test_data |
4444 | - from zim.fs import Dir |
4445 | - from zim.notebook import init_notebook, Notebook |
4446 | - |
4447 | - dir = Dir(create_tmp_dir(name)) |
4448 | - init_notebook(dir) |
4449 | - notebook = Notebook(dir=dir) |
4450 | - for name, text in get_test_data('wiki'): |
4451 | - page = notebook.get_page(Path(name)) |
4452 | - page.parse('wiki', text) |
4453 | - notebook.store_page(page) |
4454 | - |
4455 | - return notebook |
4456 | - |
4457 | - |
4458 | + # TODO test Name |
4459 | + |
4460 | + |
4461 | +@tests.slowTest |
4462 | class TestSearchFiles(TestSearch): |
4463 | |
4464 | - slowTest = True |
4465 | - |
4466 | def setUp(self): |
4467 | - self.notebook = get_files_notebook('search_TestSearchFiles') |
4468 | + path = self.create_tmp_dir() |
4469 | + self.notebook = tests.new_files_notebook(path) |
4470 | |
4471 | def runTest(self): |
4472 | '''Test search API with file based notebook''' |
4473 | |
4474 | === modified file 'tests/stores.py' |
4475 | --- tests/stores.py 2011-02-19 16:27:44 +0000 |
4476 | +++ tests/stores.py 2011-06-04 21:27:03 +0000 |
4477 | @@ -13,6 +13,7 @@ |
4478 | |
4479 | from zim.fs import * |
4480 | from zim.fs import FileWriteError |
4481 | +from zim.errors import TrashNotSupportedError |
4482 | from zim.notebook import Notebook, Path, LookupError, PageExistsError |
4483 | import zim.stores |
4484 | from zim.formats import ParseTree |
4485 | @@ -120,7 +121,7 @@ |
4486 | #~ pprint.pprint(self.index) |
4487 | #~ pprint.pprint(names) |
4488 | self.assertTrue(u'utf8:\u03b1\u03b2\u03b3' in names) # Check usage of unicode |
4489 | - self.assertEqualDiffData(names, self.index) |
4490 | + self.assertEqual(names, self.index) |
4491 | |
4492 | |
4493 | class TestStoresMemory(TestReadOnlyStore, tests.TestCase): |
4494 | @@ -130,7 +131,7 @@ |
4495 | store = zim.stores.get_store('memory') |
4496 | self.store = store.Store(path=Path(':'), notebook=Notebook()) |
4497 | self.index = set() |
4498 | - for name, text in tests.get_test_data('wiki'): |
4499 | + for name, text in tests.WikiTestData: |
4500 | self.store.set_node(Path(name), text) |
4501 | self.index.add(name) |
4502 | self.normalize_index() |
4503 | @@ -143,14 +144,14 @@ |
4504 | self.assertTrue(page.get_parsetree()) |
4505 | self.assertTrue('Foo' in ''.join(page.dump('plain'))) |
4506 | self.assertFalse(page.modified) |
4507 | - wikitext = tests.get_test_data_page('wiki', 'roundtrip') |
4508 | + wikitext = tests.WikiTestData.get('roundtrip') |
4509 | page.parse('wiki', wikitext) |
4510 | self.assertTrue(page.modified) |
4511 | self.store.store_page(page) |
4512 | self.assertFalse(page.modified) |
4513 | - self.assertEqualDiff(''.join(page.dump('wiki')), wikitext) |
4514 | + self.assertEqual(''.join(page.dump('wiki')), wikitext) |
4515 | page = self.store.get_page(Path('Test:foo')) |
4516 | - self.assertEqualDiff(''.join(page.dump('wiki')), wikitext) |
4517 | + self.assertEqual(''.join(page.dump('wiki')), wikitext) |
4518 | |
4519 | # check test setup OK |
4520 | for path in (Path('Test:BAR'), Path('NewPage')): |
4521 | @@ -187,7 +188,10 @@ |
4522 | self.assertFalse(page.hascontent) |
4523 | |
4524 | # let's delete the newpath again |
4525 | - self.assertTrue(self.store.delete_page(newpath)) |
4526 | + page = self.store.get_page(newpath) |
4527 | + self.assertTrue(self.store.delete_page(page)) |
4528 | + self.assertFalse(page.haschildren) |
4529 | + self.assertFalse(page.hascontent) |
4530 | page = self.store.get_page(newpath) |
4531 | self.assertFalse(page.haschildren) |
4532 | self.assertFalse(page.hascontent) |
4533 | @@ -223,9 +227,34 @@ |
4534 | page = self.store.get_page(Path('NewPage')) |
4535 | self.assertFalse(page.hascontent) |
4536 | |
4537 | - # TODO test getting a non-existing page |
4538 | - # TODO test if children uses namespace objects |
4539 | - # TODO test move, delete, read, write |
4540 | + # check trashing |
4541 | + trashing = True |
4542 | + try: |
4543 | + page = self.store.get_page(Path('TrashMe')) |
4544 | + self.assertTrue(page.haschildren) |
4545 | + self.assertTrue(page.hascontent) |
4546 | + self.store.trash_page(page) |
4547 | + self.assertFalse(page.haschildren) |
4548 | + self.assertFalse(page.hascontent) |
4549 | + page = self.store.get_page(Path('TrashMe')) |
4550 | + self.assertFalse(page.haschildren) |
4551 | + self.assertFalse(page.hascontent) |
4552 | + except TrashNotSupportedError: |
4553 | + trashing = False |
4554 | + print '(trashing not supported for this store)' |
4555 | + self.assertTrue(page.haschildren) |
4556 | + self.assertTrue(page.hascontent) |
4557 | + page = self.store.get_page(Path('TrashMe')) |
4558 | + self.assertTrue(page.haschildren) |
4559 | + self.assertTrue(page.hascontent) |
4560 | + |
4561 | + page = self.store.get_page(Path('NonExistingPage')) |
4562 | + if trashing: |
4563 | + # fail silently for non-existing page |
4564 | + self.assertFalse(self.store.trash_page(page)) |
4565 | + else: |
4566 | + # check error consistent |
4567 | + self.assertRaises(TrashNotSupportedError, self.store.trash_page, page) |
4568 | |
4569 | |
4570 | class TextXMLStore(TestReadOnlyStore, tests.TestCase): |
4571 | @@ -265,17 +294,16 @@ |
4572 | page = self.store.get_page(Path('Foo:Bar')) |
4573 | self.assertEqual(page.dump(format='wiki'), ['Foooo Barrr\n']) |
4574 | ref = self.xml.replace("'", '"') |
4575 | - self.assertEqualDiff(''.join(self.store.dump()), ref) |
4576 | - |
4577 | - |
4578 | + self.assertEqual(''.join(self.store.dump()), ref) |
4579 | + |
4580 | + |
4581 | +@tests.slowTest |
4582 | class TestFiles(TestStoresMemory): |
4583 | '''Test the store.files module''' |
4584 | |
4585 | - slowTest = True |
4586 | - |
4587 | def setUp(self): |
4588 | TestStoresMemory.setUp(self) |
4589 | - tmpdir = tests.create_tmp_dir(u'stores_TestFiles_\u0421\u0430\u0439') |
4590 | + tmpdir = self.create_tmp_dir(u'_some_utf8_here_\u0421\u0430\u0439') |
4591 | self.dir = Dir([tmpdir, 'store-files']) |
4592 | self.mem = self.store |
4593 | store = zim.stores.get_store('files') |
4594 | @@ -349,4 +377,3 @@ |
4595 | |
4596 | def exists(self): |
4597 | return len(self.text) > 0 |
4598 | - |
4599 | |
4600 | === added file 'tests/tags.py' |
4601 | --- tests/tags.py 1970-01-01 00:00:00 +0000 |
4602 | +++ tests/tags.py 2011-06-04 21:27:03 +0000 |
4603 | @@ -0,0 +1,357 @@ |
4604 | +# -*- coding: utf-8 -*- |
4605 | + |
4606 | +# Copyright 2011 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
4607 | + |
4608 | +import tests |
4609 | + |
4610 | +import gtk |
4611 | +import pango |
4612 | + |
4613 | +from zim.index import Index, IndexPath, IndexTag |
4614 | +from zim.notebook import Path |
4615 | +from zim.gui.pageindex import FGCOLOR_COL, \ |
4616 | + EMPTY_COL, NAME_COL, PATH_COL, STYLE_COL |
4617 | + # Explicitly don't import * from pageindex, make clear what we re-use |
4618 | +from zim.config import ListDict |
4619 | +from zim.plugins.tags import * |
4620 | + |
4621 | + |
4622 | +def color_to_string(color): |
4623 | + # helper method for comparing gtk.gdk.Color objects |
4624 | + return '%i,%i,%i' % (color.red, color.green, color.blue) |
4625 | + |
4626 | + |
4627 | +@tests.slowTest |
4628 | +class TestTaggedPageTreeStore(tests.TestCase): |
4629 | + |
4630 | + def setUp(self): |
4631 | + self.storeclass = TaggedPageTreeStore |
4632 | + self.viewclass = TagsPageTreeView |
4633 | + self.notebook = tests.new_notebook() |
4634 | + self.index = self.notebook.index |
4635 | + |
4636 | + def runTest(self): |
4637 | + '''Test TaggedPageTreeStore index interface''' |
4638 | + # This is one big test instead of seperate sub tests because in the |
4639 | + # subclass we generate a file based notebook in setUp, and we do not |
4640 | + # want to do that many times. |
4641 | + # Hooking up the treeview as well just to see if we get any errors |
4642 | + # From the order the signals are generated. |
4643 | + |
4644 | + ui = MockUI() |
4645 | + ui.notebook = self.notebook |
4646 | + ui.page = Path('Test:foo') |
4647 | + self.assertTrue(self.notebook.get_page(ui.page).exists()) |
4648 | + |
4649 | + treestore = self.storeclass(self.index) |
4650 | + self.assertEqual(treestore.get_flags(), 0) |
4651 | + self.assertEqual(treestore.get_n_columns(), 5) |
4652 | + treeview = self.viewclass(ui, treestore) |
4653 | + model = treeview.get_model() |
4654 | + if isinstance(model, gtk.TreeModelFilter): |
4655 | + model = model.get_model() # look inside filtered model |
4656 | + self.assertEqual(model, treestore) |
4657 | + |
4658 | + self.assertEqual(treestore.get_flags(), 0) |
4659 | + self.assertEqual(treestore.get_n_columns(), 5) |
4660 | + |
4661 | + self.index.update(callback=tests.gtk_process_events) |
4662 | + tests.gtk_process_events() |
4663 | + |
4664 | + #~ treeview = PageTreeView(None) # just run hidden to check errors |
4665 | + #~ treeview.set_model(treestore) |
4666 | + |
4667 | + n = treestore.on_iter_n_children(None) |
4668 | + self.assertTrue(n > 0) |
4669 | + n = treestore.iter_n_children(None) |
4670 | + self.assertTrue(n > 0) |
4671 | + |
4672 | + for i in range(treestore.get_n_columns()): |
4673 | + self.assertTrue(not treestore.get_column_type(i) is None) |
4674 | + |
4675 | + # Quick check for basic methods |
4676 | + iter = treestore.on_get_iter((0,)) |
4677 | + self.assertTrue(isinstance(iter, (PageTreeIter, PageTreeTagIter))) |
4678 | + if self.storeclass is TaggedPageTreeStore: |
4679 | + self.assertTrue(isinstance(iter, PageTreeIter)) |
4680 | + self.assertTrue(isinstance(iter.indexpath, IndexPath)) |
4681 | + self.assertFalse(iter.indexpath.isroot) |
4682 | + else: |
4683 | + self.assertTrue(isinstance(iter, PageTreeTagIter)) |
4684 | + self.assertTrue(isinstance(iter.indextag, IndexTag)) |
4685 | + basename = treestore.on_get_value(iter, 0) |
4686 | + self.assertTrue(len(basename) > 0) |
4687 | + self.assertEqual(iter.treepath, (0,)) |
4688 | + self.assertEqual(treestore.on_get_path(iter), (0,)) |
4689 | + if self.storeclass is TaggedPageTreeStore: |
4690 | + self.assertEqual(treestore.get_treepath(iter.indexpath), (0,)) |
4691 | + self.assertEqual(treestore.get_treepath(Path(iter.indexpath.name)), (0,)) |
4692 | + else: |
4693 | + self.assertEqual(treestore.get_treepath(iter.indextag), (0,)) |
4694 | + |
4695 | + iter2 = treestore.on_iter_children(None) |
4696 | + if self.storeclass is TaggedPageTreeStore: |
4697 | + self.assertEqual(iter2.indexpath, iter.indexpath) |
4698 | + else: |
4699 | + self.assertEqual(iter2.indextag, iter.indextag) |
4700 | + |
4701 | + self.assertTrue(treestore.on_get_iter((20,20,20,20,20)) is None) |
4702 | + self.assertTrue(treestore.get_treepath(Path('nonexisting')) is None) |
4703 | + self.assertRaises(ValueError, treestore.get_treepath, Path(':')) |
4704 | + |
4705 | + # Now walk through the whole tree testing the API |
4706 | + nitems = 0 |
4707 | + path = (0,) |
4708 | + prevpath = None |
4709 | + while path: |
4710 | + #~ print '>>', path |
4711 | + assert path != prevpath, 'Prevent infinite loop' |
4712 | + nitems += 1 |
4713 | + prevpath = path |
4714 | + |
4715 | + iter = treestore.get_iter(path) |
4716 | + self.assertEqual(treestore.get_path(iter), tuple(path)) |
4717 | + |
4718 | + if isinstance(treestore.on_get_iter(path), PageTreeIter): |
4719 | + self._check_indexpath_iter(treestore, iter, path) |
4720 | + else: |
4721 | + self._check_indextag_iter(treestore, iter, path) |
4722 | + |
4723 | + # Determine how to continue |
4724 | + if treestore.iter_has_child(iter): |
4725 | + path = path + (0,) |
4726 | + else: |
4727 | + path = path[:-1] + (path[-1]+1,) # increase last member |
4728 | + while path: |
4729 | + try: |
4730 | + treestore.get_iter(path) |
4731 | + except ValueError: |
4732 | + path = path[:-1] |
4733 | + if len(path): |
4734 | + path = path[:-1] + (path[-1]+1,) # increase last member |
4735 | + else: |
4736 | + break |
4737 | + |
4738 | + self.assertTrue(nitems > 10) # double check sanity of loop |
4739 | + |
4740 | + # Check if all the signals go OK |
4741 | + treestore.disconnect_index() |
4742 | + del treestore |
4743 | + self.index.flush() |
4744 | + treestore = self.storeclass(self.index) |
4745 | + treeview = TagsPageTreeView(ui, treestore) |
4746 | + self.index.update(callback=tests.gtk_process_events) |
4747 | + |
4748 | + # Try some TreeView methods |
4749 | + path = Path('Test:foo') |
4750 | + self.assertTrue(treeview.select_page(path)) |
4751 | + self.assertEqual(treeview.get_selected_path(), path) |
4752 | + treepath = treeview.get_model().get_treepath(path) |
4753 | + self.assertTrue(not treepath is None) |
4754 | + col = treeview.get_column(0) |
4755 | + treeview.row_activated(treepath, col) |
4756 | + |
4757 | + #~ treeview.emit('popup-menu') |
4758 | + treeview.emit('insert-link', path) |
4759 | + treeview.emit('copy') |
4760 | + |
4761 | + # Check if all the signals go OK in delete |
4762 | + for page in reversed(list(self.notebook.walk())): # delete bottom up |
4763 | + self.notebook.delete_page(page) |
4764 | + tests.gtk_process_events() |
4765 | + |
4766 | + def _check_indexpath_iter(self, treestore, iter, path): |
4767 | + # checks specific for nodes that map to IndexPath object |
4768 | + indexpath = treestore.get_indexpath(iter) |
4769 | + self.assertTrue(path in treestore.get_treepaths(indexpath)) |
4770 | + |
4771 | + page = self.notebook.get_page(indexpath) |
4772 | + self.assertEqual(treestore.get_value(iter, NAME_COL), page.basename) |
4773 | + self.assertEqual(treestore.get_value(iter, PATH_COL), page) |
4774 | + if page.hascontent or page.haschildren: |
4775 | + self.assertEqual(treestore.get_value(iter, EMPTY_COL), False) |
4776 | + self.assertEqual(treestore.get_value(iter, STYLE_COL), pango.STYLE_NORMAL) |
4777 | + self.assertEqual( |
4778 | + color_to_string( treestore.get_value(iter, FGCOLOR_COL) ), |
4779 | + color_to_string( treestore.NORMAL_COLOR) ) |
4780 | + else: |
4781 | + self.assertEqual(treestore.get_value(iter, EMPTY_COL), True) |
4782 | + self.assertEqual(treestore.get_value(iter, STYLE_COL), pango.STYLE_ITALIC) |
4783 | + self.assertEqual( |
4784 | + color_to_string( treestore.get_value(iter, FGCOLOR_COL) ), |
4785 | + color_to_string( treestore.EMPTY_COLOR) ) |
4786 | + |
4787 | + self._check_iter_children(treestore, iter, path, indexpath.haschildren) |
4788 | + |
4789 | + def _check_indextag_iter(self, treestore, iter, path): |
4790 | + # checks specific for nodes that map to IndexTag object |
4791 | + self.assertTrue(treestore.get_indexpath(iter) is None) |
4792 | + |
4793 | + indextag = treestore.get_indextag(iter) |
4794 | + self.assertTrue(path in treestore.get_treepaths(indextag)) |
4795 | + |
4796 | + self.assertEqual(treestore.get_value(iter, NAME_COL), indextag.name) |
4797 | + self.assertEqual(treestore.get_value(iter, PATH_COL), indextag) |
4798 | + if indextag == treestore.untagged: |
4799 | + self.assertEqual(treestore.get_value(iter, EMPTY_COL), True) |
4800 | + self.assertEqual(treestore.get_value(iter, STYLE_COL), pango.STYLE_ITALIC) |
4801 | + self.assertEqual( |
4802 | + color_to_string( treestore.get_value(iter, FGCOLOR_COL) ), |
4803 | + color_to_string( treestore.EMPTY_COLOR) ) |
4804 | + else: |
4805 | + self.assertEqual(treestore.get_value(iter, EMPTY_COL), False) |
4806 | + self.assertEqual(treestore.get_value(iter, STYLE_COL), pango.STYLE_NORMAL) |
4807 | + self.assertEqual( |
4808 | + color_to_string( treestore.get_value(iter, FGCOLOR_COL) ), |
4809 | + color_to_string( treestore.NORMAL_COLOR) ) |
4810 | + |
4811 | + if indextag == treestore.untagged: |
4812 | + haschildren = self.index.n_list_untagged_root_pages() > 0 |
4813 | + else: |
4814 | + haschildren = self.index.n_list_tagged_pages(indextag) > 0 |
4815 | + self._check_iter_children(treestore, iter, path, haschildren) |
4816 | + |
4817 | + def _check_iter_children(self, treestore, iter, path, haschildren): |
4818 | + # Check API for children is consistent |
4819 | + if haschildren: |
4820 | + self.assertTrue(treestore.iter_has_child(iter)) |
4821 | + child = treestore.iter_children(iter) |
4822 | + self.assertTrue(not child is None) |
4823 | + child = treestore.iter_nth_child(iter, 0) |
4824 | + self.assertTrue(not child is None) |
4825 | + parent = treestore.iter_parent(child) |
4826 | + self.assertEqual(treestore.get_path(parent), path) |
4827 | + childpath = treestore.get_path(child) |
4828 | + self.assertEqual( |
4829 | + childpath, tuple(path) + (0,)) |
4830 | + n = treestore.iter_n_children(iter) |
4831 | + for i in range(1, n): |
4832 | + child = treestore.iter_next(child) |
4833 | + childpath = treestore.get_path(child) |
4834 | + self.assertEqual( |
4835 | + childpath, tuple(path) + (i,)) |
4836 | + child = treestore.iter_next(child) |
4837 | + self.assertTrue(child is None) |
4838 | + else: |
4839 | + self.assertTrue(not treestore.iter_has_child(iter)) |
4840 | + child = treestore.iter_children(iter) |
4841 | + self.assertTrue(child is None) |
4842 | + child = treestore.iter_nth_child(iter, 0) |
4843 | + self.assertTrue(child is None) |
4844 | + |
4845 | + |
4846 | +@tests.slowTest |
4847 | +class TestTagsPageTreeStore(TestTaggedPageTreeStore): |
4848 | + |
4849 | + def setUp(self): |
4850 | + TestTaggedPageTreeStore.setUp(self) |
4851 | + self.storeclass = TagsPageTreeStore |
4852 | + self.viewclass = TagsPageTreeView |
4853 | + |
4854 | + def runTest(self): |
4855 | + '''Test TagsPageTreeStore index interface''' |
4856 | + TestTaggedPageTreeStore.runTest(self) |
4857 | + |
4858 | + |
4859 | +@tests.slowTest |
4860 | +class TestTagPluginWidget(tests.TestCase): |
4861 | + |
4862 | + def runTest(self): |
4863 | + ui = MockUI() |
4864 | + ui.notebook = tests.new_notebook() |
4865 | + |
4866 | + plugin = tests.MockObject() |
4867 | + plugin.ui = ui |
4868 | + plugin.uistate = ListDict() |
4869 | + |
4870 | + widget = TagsPluginWidget(plugin) |
4871 | + |
4872 | + # Excersize all model switches and check we still have a sane state |
4873 | + widget.toggle_treeview() |
4874 | + widget.toggle_treeview() |
4875 | + |
4876 | + path = Path('Test:foo') |
4877 | + treepath = widget.treeview.get_model().get_treepath(path) |
4878 | + self.assertTrue(not treepath is None) |
4879 | + |
4880 | + widget.disconnect_model() |
4881 | + widget.reload_model() |
4882 | + |
4883 | + path = Path('Test:foo') |
4884 | + treepath = widget.treeview.get_model().get_treepath(path) |
4885 | + self.assertTrue(not treepath is None) |
4886 | + |
4887 | + # Check signals |
4888 | + #~ widget.treeview.emit('popup-menu') |
4889 | + widget.treeview.emit('insert-link', path) |
4890 | + |
4891 | + # Check tag filtering |
4892 | + cloud = widget.tagcloud |
4893 | + self.assertEqual(cloud.get_tag_filter(), None) |
4894 | + tag = None |
4895 | + for button in cloud.get_children(): |
4896 | + if button.indextag.name == 'tags': |
4897 | + tag = button.indextag |
4898 | + button.clicked() |
4899 | + break |
4900 | + else: |
4901 | + raise AssertionError, 'No button for @tags ?' |
4902 | + |
4903 | + selected, filtered = cloud.get_tag_filter() |
4904 | + self.assertEqual(selected, [tag]) |
4905 | + self.assertTrue(len(filtered) > 3) |
4906 | + self.assertTrue(tag in filtered) |
4907 | + |
4908 | + self.assertTrue(not widget.treeview._tag_filter is None) |
4909 | + |
4910 | + # check filtering in treestore |
4911 | + tagfilter = (selected, filtered) |
4912 | + filtered = frozenset(filtered) |
4913 | + |
4914 | + def toplevel(model): |
4915 | + iter = model.get_iter_first() |
4916 | + assert not iter is None |
4917 | + while not iter is None: |
4918 | + yield iter |
4919 | + iter = model.iter_next(iter) |
4920 | + |
4921 | + def childiter(model, iter): |
4922 | + iter = model.iter_children(iter) |
4923 | + assert not iter is None |
4924 | + while not iter is None: |
4925 | + yield iter |
4926 | + iter = model.iter_next(iter) |
4927 | + |
4928 | + self.assertEqual(plugin.uistate['treeview'], 'tagged') |
4929 | + filteredmodel = widget.treeview.get_model() |
4930 | + for iter in toplevel(filteredmodel): |
4931 | + path = filteredmodel.get_indexpath(iter) |
4932 | + self.assertTrue(not path is None) |
4933 | + tags = list(ui.notebook.index.list_tags(path)) |
4934 | + tags = frozenset(tags) |
4935 | + self.assertTrue(tags >= filtered) |
4936 | + treepaths = filteredmodel.get_treepaths(path) |
4937 | + self.assertTrue(filteredmodel.get_path(iter) in treepaths) |
4938 | + |
4939 | + widget.toggle_treeview() |
4940 | + self.assertEqual(plugin.uistate['treeview'], 'tags') |
4941 | + filteredmodel = widget.treeview.get_model() |
4942 | + for iter in toplevel(filteredmodel): |
4943 | + self.assertEqual(filteredmodel.get_indexpath(iter), None) |
4944 | + # toplevel has tags, not pages |
4945 | + tag = filteredmodel[iter][PATH_COL] |
4946 | + self.assertTrue(tag in filtered) |
4947 | + for iter in childiter(filteredmodel, iter): |
4948 | + path = filteredmodel.get_indexpath(iter) |
4949 | + self.assertTrue(not path is None) |
4950 | + tags = list(ui.notebook.index.list_tags(path)) |
4951 | + tags = frozenset(tags) |
4952 | + self.assertTrue(tags >= filtered) |
4953 | + treepaths = filteredmodel.get_treepaths(path) |
4954 | + self.assertTrue(filteredmodel.get_path(iter) in treepaths) |
4955 | + |
4956 | + |
4957 | +class MockUI(tests.MockObject): |
4958 | + |
4959 | + page = None |
4960 | + notebook = None |
4961 | |
4962 | === modified file 'tests/tasklist.py' |
4963 | --- tests/tasklist.py 2011-02-19 16:27:44 +0000 |
4964 | +++ tests/tasklist.py 2011-06-04 21:27:03 +0000 |
4965 | @@ -2,16 +2,17 @@ |
4966 | |
4967 | # Copyright 2011 Jaap Karssenberg <jaap.karssenberg@gmail.com> |
4968 | |
4969 | -from tests import TestCase, MockObject, get_test_notebook |
4970 | +import tests |
4971 | + |
4972 | |
4973 | import zim.plugins |
4974 | import zim.config |
4975 | import zim.formats |
4976 | |
4977 | |
4978 | -class TestTaskList(TestCase): |
4979 | +class TestTaskList(tests.TestCase): |
4980 | |
4981 | - def runTest(self): |
4982 | + def testIndexing(self): |
4983 | '''Check indexing of tasklist plugin''' |
4984 | klass = zim.plugins.get_plugin('tasklist') |
4985 | ui = MockUI() |
4986 | @@ -49,24 +50,32 @@ |
4987 | tasks = plugin.extract_tasks(tree) |
4988 | labels = [task[-1] for task in tasks] |
4989 | self.assertEqual(labels, ['A', 'B', 'C', 'D', 'E', 'FIXME: dus']) |
4990 | - self.assertEqualDiff(tree.tostring(), origtree) |
4991 | + self.assertEqual(tree.tostring(), origtree) |
4992 | # extract should not modify the tree |
4993 | |
4994 | plugin.preferences['all_checkboxes'] = False |
4995 | tasks = plugin.extract_tasks(tree) |
4996 | labels = [task[-1] for task in tasks] |
4997 | self.assertEqual(labels, ['A', 'B', 'C', 'FIXME: dus']) |
4998 | - self.assertEqualDiff(tree.tostring(), origtree) |
4999 | + self.assertEqual(tree.tostring(), origtree) |
5000 | # extract should not modify the tree |
The diff has been truncated for viewing.