Merge lp:~dholbach/developer-ubuntu-com/1568871 into lp:developer-ubuntu-com

Proposed by Daniel Holbach on 2016-04-15
Status: Merged
Merged at revision: 209
Proposed branch: lp:~dholbach/developer-ubuntu-com/1568871
Merge into: lp:developer-ubuntu-com
Diff against target: 1785 lines (+840/-358)
18 files modified
md_importer/importer/article.py (+22/-60)
md_importer/importer/process.py (+23/-17)
md_importer/importer/publish.py (+143/-74)
md_importer/importer/repo.py (+47/-87)
md_importer/management/commands/import_md.py (+1/-1)
md_importer/migrations/0003_add_herotour_template.py (+19/-0)
md_importer/migrations/0004_move_from_page_object_to_url_string.py (+24/-0)
md_importer/models.py (+8/-3)
md_importer/tests/test_article.py (+155/-0)
md_importer/tests/test_branch_fetch.py (+4/-4)
md_importer/tests/test_branch_import.py (+53/-38)
md_importer/tests/test_import_process.py (+268/-6)
md_importer/tests/test_link_rewrite.py (+14/-13)
md_importer/tests/test_misc.py (+6/-7)
md_importer/tests/test_snappy_import.py (+7/-37)
md_importer/tests/test_utils.py (+5/-4)
md_importer/tests/test_website_import.py (+4/-4)
md_importer/tests/utils.py (+37/-3)
To merge this branch: bzr merge lp:~dholbach/developer-ubuntu-com/1568871
Reviewer Review Type Date Requested Status
Ubuntu App Developer site developers 2016-04-15 Pending
Review via email: mp+292024@code.launchpad.net

Description of the Change

List of important changes (high level overview)
 - added tests and assertions
 - remove the implicit addition of redirects (we do this in JS now
   and will have an app in the future)
 - remove the special-casing of snappy vs non-snappy docs (it was
   brittle and we will have to build proper versioning support
   anyway)
 - one way to look up pages
 - proper distinction between drafts vs. public page objects
 - refactor all page creation/updating logic into separate
   ArticlePage class
 - make index pages inherit from ArticlePage

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 'md_importer/importer/article.py'
2--- md_importer/importer/article.py 2016-03-21 13:08:22 +0000
3+++ md_importer/importer/article.py 2016-04-18 15:28:31 +0000
4@@ -8,10 +8,15 @@
5
6 from . import (
7 DEFAULT_LANG,
8+ DEFAULT_TEMPLATE,
9 MARKDOWN_EXTENSIONS,
10 SUPPORTED_ARTICLE_TYPES,
11 )
12-from .publish import get_or_create_page, slugify, update_page
13+from .publish import (
14+ ArticlePage,
15+ ParentNotFoundException,
16+ slugify,
17+)
18
19 if sys.version_info.major == 2:
20 from urlparse import urlparse
21@@ -20,9 +25,10 @@
22
23
24 class Article:
25- def __init__(self, fn, write_to, advertise, template):
26+ def __init__(self, fn, write_to, advertise=True,
27+ template=DEFAULT_TEMPLATE):
28 self.html = None
29- self.page = None
30+ self.article_page = None
31 self.title = ""
32 self.fn = fn
33 self.write_to = slugify(self.fn)
34@@ -116,67 +122,23 @@
35
36 def add_to_db(self):
37 '''Publishes pages in their branch alias namespace.'''
38- self.page = get_or_create_page(
39- title=self.title, full_url=self.full_url, menu_title=self.title,
40- html=self.html, in_navigation=self.advertise,
41- template=self.template)
42- if not self.page:
43+ try:
44+ self.article_page = ArticlePage(
45+ title=self.title, full_url=self.full_url,
46+ menu_title=self.title, html=self.html,
47+ in_navigation=self.advertise, template=self.template)
48+ except ParentNotFoundException:
49 return False
50 self.full_url = re.sub(
51 r'^\/None\/', '/{}/'.format(DEFAULT_LANG),
52- self.page.get_absolute_url())
53+ self.article_page.draft.get_absolute_url())
54 return True
55
56 def publish(self):
57 if self.links_rewritten:
58- update_page(self.page, title=self.title, full_url=self.full_url,
59- menu_title=self.title, html=self.html,
60- in_navigation=self.advertise, template=self.template)
61- if self.page.is_dirty(DEFAULT_LANG):
62- self.page.publish(DEFAULT_LANG)
63- if self.page.get_public_object():
64- self.page = self.page.get_public_object()
65- return self.page
66-
67-
68-class SnappyArticle(Article):
69- release_alias = None
70-
71- def read(self):
72- if not Article.read(self):
73- return False
74- matches = re.findall(r'snappy/guides/(\S+?)/\S+?',
75- self.full_url)
76- if matches:
77- self.release_alias = matches[0]
78- self._make_snappy_mods()
79- return True
80-
81- def _make_snappy_mods(self):
82- # Make sure the reader knows which documentation she is browsing
83- if self.release_alias and self.release_alias != 'current':
84- before = (u"<div class=\"row no-border\">\n"
85- "<div class=\"eight-col\">\n")
86- after = (u"<div class=\"row no-border\">\n"
87- "<div class=\"box pull-three three-col\">"
88- "<p>You are browsing the Snappy <code>%s</code> "
89- "documentation.</p>"
90- "<p><a href=\"/snappy/guides/current/%s\">"
91- "Back to the latest stable release &rsaquo;"
92- "</a></p></div>\n"
93- "<div class=\"eight-col\">\n") % (self.release_alias,
94- self.slug, )
95- self.html = self.html.replace(before, after)
96-
97- def add_to_db(self):
98- if self.release_alias == "current":
99- # Add a guides/<page> redirect to guides/current/<page>
100- page = get_or_create_page(
101- title=self.title,
102- full_url=self.full_url.replace('/current', ''),
103- redirect="/snappy/guides/current/{}".format(self.slug))
104- if not page:
105- return False
106- elif self.release_alias:
107- self.title += " (%s)" % (self.release_alias,)
108- return Article.add_to_db(self)
109+ self.article_page.update(
110+ title=self.title, full_url=self.full_url,
111+ menu_title=self.title, html=self.html,
112+ in_navigation=self.advertise, template=self.template)
113+ self.article_page.publish()
114+ return self.article_page.page
115
116=== modified file 'md_importer/importer/process.py'
117--- md_importer/importer/process.py 2016-03-08 13:07:19 +0000
118+++ md_importer/importer/process.py 2016-04-18 15:28:31 +0000
119@@ -1,12 +1,13 @@
120-from django.core.management import call_command
121-
122 import datetime
123+import logging
124 import pytz
125 import shutil
126 import tempfile
127
128-from md_importer.importer.repo import create_repo
129+from django.core.management import call_command
130
131+from md_importer.importer.publish import find_page
132+from md_importer.importer.repo import Repo
133 from md_importer.models import (
134 ExternalDocsBranchImportDirective,
135 ImportedArticle,
136@@ -15,10 +16,10 @@
137
138 def process_branch(branch):
139 tempdir = tempfile.mkdtemp()
140- repo = create_repo(tempdir, branch.origin, branch.branch_name,
141- branch.post_checkout_command)
142+ repo = Repo(tempdir, branch.origin, branch.branch_name,
143+ branch.post_checkout_command)
144 if repo.get() != 0:
145- return False
146+ return None
147 for directive in ExternalDocsBranchImportDirective.objects.filter(
148 external_docs_branch=branch):
149 repo.add_directive(directive.import_from,
150@@ -26,29 +27,34 @@
151 directive.advertise,
152 directive.template)
153 if not repo.execute_import_directives():
154- return False
155+ return None
156 if not repo.publish():
157- return False
158+ return None
159 timestamp = datetime.datetime.now(pytz.utc)
160
161 # Update data in ImportedArticle table
162 for page in repo.pages:
163- if ImportedArticle.objects.filter(branch=branch, page=page).count():
164+ url = page.get_absolute_url()
165+ if ImportedArticle.objects.filter(branch=branch, url=url).count():
166 imported_article = ImportedArticle.objects.filter(
167- branch=branch, page=page)[0]
168- imported_article.last_import = datetime.datetime.now(pytz.utc)
169+ branch=branch, url=url)[0]
170+ imported_article.last_import = timestamp
171 imported_article.save()
172 else:
173- ImportedArticle.objects.get_or_create(
174+ imported_article, created = ImportedArticle.objects.get_or_create(
175 branch=branch,
176- page=page,
177- last_import=datetime.datetime.now(pytz.utc))
178+ url=url,
179+ last_import=timestamp)
180
181 # Remove old entries
182 for imported_article in ImportedArticle.objects.filter(
183 branch=branch, last_import__lt=timestamp):
184- imported_article.page.delete()
185- imported_article.delete()
186+ page = find_page(imported_article.url)
187+ if not page:
188+ logging.error('Page {} not found for deletion.'.format(url))
189+ else:
190+ page.delete()
191+ imported_article.delete()
192
193 # The import is done, now let's clean up.
194 imported_page_ids = [p.id for p in repo.pages
195@@ -59,4 +65,4 @@
196
197 # https://stackoverflow.com/questions/33284171/
198 call_command('cms', 'fix-tree')
199- return True
200+ return repo
201
202=== modified file 'md_importer/importer/publish.py'
203--- md_importer/importer/publish.py 2016-04-04 14:07:27 +0000
204+++ md_importer/importer/publish.py 2016-04-18 15:28:31 +0000
205@@ -5,7 +5,7 @@
206 from md_importer.importer.tools import remove_leading_and_trailing_slash
207
208 from cms.api import create_page, add_plugin
209-from cms.models import Page, Title
210+from cms.models import Page
211 from cms.utils.page_resolver import get_page_from_path
212 from djangocms_text_ckeditor.html import clean_html
213
214@@ -15,6 +15,118 @@
215 import os
216
217
218+class ParentNotFoundException(Exception):
219+ def __init__(self, parent_url):
220+ self.parent_url = parent_url
221+
222+ def __str__(self):
223+ return repr(self.parent_url)
224+
225+
226+class ArticlePage:
227+ def _text_plugin_needs_update(self, html):
228+ if _compare_html(html, self.draft_text_plugin.body):
229+ return False
230+ if self.text_plugin and _compare_html(html, self.text_plugin.body):
231+ return False
232+ return True
233+
234+ def update(self, title, full_url, menu_title=None, in_navigation=True,
235+ html=None, template=None):
236+ if self.draft.get_title() != title:
237+ self.draft.title = title
238+ if self.draft.get_menu_title() != menu_title:
239+ self.draft.menu_title = menu_title
240+ if self.draft.in_navigation != in_navigation:
241+ self.draft.in_navigation = in_navigation
242+ if self.draft.template != template:
243+ self.draft.template = template
244+ if html:
245+ (self.draft_placeholder,
246+ self.draft_text_plugin) = get_text_plugin(self.draft)
247+ if self.page:
248+ (self.placeholder,
249+ self.text_plugin) = get_text_plugin(self.page)
250+ if self.draft_text_plugin:
251+ if self._text_plugin_needs_update(html):
252+ self.draft_text_plugin.body = html
253+ self.draft_text_plugin.save()
254+ else:
255+ # Reset draft
256+ self.draft.revert(DEFAULT_LANG)
257+ else:
258+ self.draft_plugin = add_plugin(
259+ self.draft_placeholder, 'RawHtmlPlugin', DEFAULT_LANG,
260+ body=html)
261+
262+ def __init__(self, title, full_url, menu_title=None, in_navigation=True,
263+ html=None, template=DEFAULT_TEMPLATE):
264+ self.page = None
265+ self.draft = None
266+ self.draft_placeholder = None
267+ self.draft_text_plugin = None
268+ self.text_plugin = None
269+ self.placeholder = None
270+ self.full_url = full_url
271+ self.title = title
272+ self.menu_title = menu_title
273+ self.in_navigation = in_navigation
274+ self.template = template
275+
276+ # First check if pages already exist.
277+ self.draft = find_page(full_url, draft=True)
278+ if not self.draft:
279+ parent = _find_parent(full_url)
280+ if not parent:
281+ raise ParentNotFoundException(
282+ 'Parent for {} not found.'.format(full_url))
283+ slug = os.path.basename(full_url)
284+ self.draft = create_page(
285+ title=title, template=template, language=DEFAULT_LANG,
286+ slug=slug, parent=parent, menu_title=menu_title,
287+ in_navigation=in_navigation, position='last-child')
288+ self.update(title, full_url, menu_title, in_navigation, html,
289+ template)
290+
291+ def publish(self):
292+ if self.draft.is_dirty(DEFAULT_LANG):
293+ self.draft.publish(DEFAULT_LANG)
294+ if self.draft.get_public_object():
295+ self.page = self.draft.get_public_object()
296+
297+
298+class IndexPage(ArticlePage):
299+ def __init__(self, title, full_url, menu_title='Overview',
300+ in_navigation=True, html='', template=DEFAULT_TEMPLATE):
301+ self.imported_articles = []
302+ self.origin = ''
303+ ArticlePage.__init__(self, title, full_url, menu_title,
304+ in_navigation, html, template)
305+ self.publish()
306+
307+ def add_imported_articles(self, imported_articles, origin):
308+ self.imported_articles = imported_articles
309+ self.origin = origin
310+ list_pages = u''
311+ for article in [a for a
312+ in self.imported_articles
313+ if a.full_url.startswith(self.full_url)]:
314+ list_pages += u'<li><a href=\"{}\">{}</a></li>'.format(
315+ unicode(os.path.basename(article.full_url)),
316+ article.title)
317+ html = (
318+ u'<div class=\"row\"><div class=\"eight-col\">\n'
319+ '<p>This section contains documentation for the '
320+ 'Snappy project.</p>'
321+ '<p><ul class=\"list-ubuntu\">{}</ul></p>\n'
322+ '<p>Auto-imported from <a '
323+ 'href=\"{}\">{}</a>.</p>\n'
324+ '</div></div>'.format(list_pages, self.origin, self.origin))
325+ self.update(self.title, self.full_url, self.menu_title,
326+ self.in_navigation, html, self.template)
327+ self.publish()
328+
329+
330 def _compare_html(html_a, html_b):
331 soup_a = BeautifulSoup(html_a, 'html5lib')
332 soup_b = BeautifulSoup(html_b, 'html5lib')
333@@ -25,17 +137,28 @@
334 return os.path.basename(filename).replace('.md', '').replace('.html', '')
335
336
337+def clean_url(url):
338+ return remove_leading_and_trailing_slash(
339+ re.sub(
340+ r'^\/None|{}\/'.format(DEFAULT_LANG),
341+ '',
342+ url))
343+
344+
345+def find_page(url, draft=False):
346+ page = get_page_from_path(clean_url(url), draft)
347+ if page and draft and not page.publisher_is_draft:
348+ return page.get_draft_object()
349+ return page
350+
351+
352 def _find_parent(full_url):
353- parent_url = remove_leading_and_trailing_slash(re.sub(
354- r'^\/None|{}\/'.format(DEFAULT_LANG),
355- '',
356- os.path.dirname(full_url)))
357 parent_url = os.path.dirname(full_url)
358 if not parent_url:
359 root = Page.objects.get_home()
360 if not root:
361 return None
362- return root.get_draft_object()
363+ return root
364 parent = get_page_from_path(parent_url, draft=True)
365 if not parent:
366 logging.error('Parent {} not found.'.format(parent_url))
367@@ -43,72 +166,18 @@
368 return parent
369
370
371-def find_text_plugin(page):
372+def get_text_plugin(page):
373+ '''Finds text plugin, creates it if necessary.'''
374+ if not page:
375+ return (None, None)
376+ placeholders = page.placeholders.all()
377+ if not placeholders:
378+ return (None, None)
379 # We create the page, so we know there's just one placeholder
380- placeholder = page.placeholders.all()[0]
381- if placeholder.get_plugins():
382- return (
383- placeholder,
384- placeholder.get_plugins()[0].get_plugin_instance()[0]
385- )
386- return (placeholder, None)
387-
388-
389-def update_page(page, title, full_url, menu_title=None,
390- in_navigation=True, redirect=None, html=None, template=None):
391- if page.get_title() != title:
392- page.title = title
393- if page.get_menu_title() != menu_title:
394- page.menu_title = menu_title
395- if page.in_navigation != in_navigation:
396- page.in_navigation = in_navigation
397- if page.get_redirect() != redirect:
398- page.redirect = redirect
399- if page.template != template:
400- page.template = template
401- if html:
402- update = True
403- (placeholder, plugin) = find_text_plugin(page)
404- if plugin:
405- if _compare_html(html, plugin.body):
406- update = False
407- elif page.get_public_object():
408- (dummy, published_plugin) = \
409- find_text_plugin(page.get_public_object())
410- if published_plugin:
411- if _compare_html(html, published_plugin.body):
412- update = False
413- if update:
414- plugin.body = html
415- plugin.save()
416- else:
417- # Reset draft
418- page.get_draft_object().revert(DEFAULT_LANG)
419- else:
420- add_plugin(
421- placeholder, 'RawHtmlPlugin',
422- DEFAULT_LANG, body=html)
423-
424-
425-def get_or_create_page(title, full_url, menu_title=None,
426- in_navigation=True, redirect=None, html=None,
427- template=DEFAULT_TEMPLATE):
428- # First check if pages already exist.
429- pages = Title.objects.select_related('page').filter(
430- path__regex=full_url).filter(publisher_is_draft=True)
431- if pages:
432- page = pages[0].page
433- update_page(page, title, full_url, menu_title, in_navigation,
434- redirect, html, template)
435- else:
436- parent = _find_parent(full_url)
437- if not parent:
438- return None
439- slug = os.path.basename(full_url)
440- page = create_page(
441- title=title, template=template, language=DEFAULT_LANG, slug=slug,
442- parent=parent, menu_title=menu_title, in_navigation=in_navigation,
443- position='last-child', redirect=redirect)
444- placeholder = page.placeholders.all()[0]
445- add_plugin(placeholder, 'RawHtmlPlugin', DEFAULT_LANG, body=html)
446- return page
447+ plugins = placeholders[0].get_plugins()
448+ if plugins:
449+ return (placeholders[0], plugins[0].get_plugin_instance()[0])
450+ plugin = add_plugin(
451+ placeholders[0], 'RawHtmlPlugin', DEFAULT_LANG,
452+ body='')
453+ return (placeholders[0], plugin)
454
455=== modified file 'md_importer/importer/repo.py'
456--- md_importer/importer/repo.py 2016-04-04 08:51:39 +0000
457+++ md_importer/importer/repo.py 2016-04-18 15:28:31 +0000
458@@ -1,9 +1,13 @@
459 from . import (
460- DEFAULT_LANG,
461 SUPPORTED_ARTICLE_TYPES,
462-)
463-from .article import Article, SnappyArticle
464-from .publish import get_or_create_page, slugify
465+ DEFAULT_TEMPLATE,
466+)
467+from .article import Article
468+from .publish import (
469+ IndexPage,
470+ ParentNotFoundException,
471+ slugify,
472+)
473 from .source import SourceCode
474
475 from md_importer.models import ExternalDocsBranchImportDirective
476@@ -13,40 +17,22 @@
477 import os
478
479
480-def create_repo(tempdir, origin, branch_name, post_checkout_command):
481- if os.path.exists(origin):
482- if 'snappy' in origin:
483- repo_class = SnappyRepo
484- else:
485- repo_class = Repo
486- else:
487- if origin.startswith('lp:snappy') or \
488- 'snappy' in origin.split(':')[1].split('.git')[0].split('/'):
489- repo_class = SnappyRepo
490- else:
491- repo_class = Repo
492- return repo_class(tempdir, origin, branch_name, post_checkout_command)
493-
494-
495 class Repo:
496 def __init__(self, tempdir, origin, branch_name, post_checkout_command):
497 self.directives = []
498 self.imported_articles = []
499 self.url_map = {}
500 self.titles = {}
501- self.index_doc_url = None
502 self.index_page = None
503- self.release_alias = None
504 # On top of the pages in imported_articles this also
505 # includes index_page
506 self.pages = []
507+ self.urls = []
508 self.origin = origin
509 self.branch_name = branch_name
510 self.post_checkout_command = post_checkout_command
511- branch_nick = os.path.basename(self.origin.replace('.git', ''))
512- self.checkout_location = os.path.join(
513- tempdir, branch_nick)
514- self.index_doc_title = branch_nick
515+ self.branch_nick = os.path.basename(self.origin.replace('.git', ''))
516+ self.checkout_location = os.path.join(tempdir, self.branch_nick)
517 self.article_class = Article
518
519 def get(self):
520@@ -99,12 +85,20 @@
521 ]
522 # If we import into a namespace and don't have an index doc,
523 # we need to write one.
524- if directive['write_to'] not in [x[1] for x in import_list]:
525- self.index_doc_url = directive['write_to']
526- if self.index_doc_url:
527- if not self._create_fake_index_page():
528- logging.error('Importing of {} aborted.'.format(self.origin))
529- return False
530+ # XXX: Right now we just create one index doc, this will change in
531+ # the near future.
532+ if directive['write_to'] not in [x[1] for x in import_list] and \
533+ not self.index_page:
534+ try:
535+ self.index_page = IndexPage(
536+ title=self.branch_nick, full_url=directive['write_to'],
537+ in_navigation=True, html='', menu_title=None,
538+ template=DEFAULT_TEMPLATE)
539+ self.pages.extend([self.index_page.page])
540+ except ParentNotFoundException:
541+ return self._abort_import(
542+ 'Could not create fake index page at {}'.format(
543+ directive['write_to']))
544 # The actual import
545 for entry in import_list:
546 article = self._read_article(
547@@ -117,12 +111,17 @@
548 # In this case the article was supported but still reading
549 # it failed, importing should be stopped here to avoid
550 # problems.
551- logging.error('Importing of {} aborted.'.format(self.origin))
552- return False
553- if self.index_doc_url:
554- self._write_fake_index_doc()
555+ return self._abort_import('Reading {} failed'.format(
556+ entry[0]))
557+ if self.index_page:
558+ self.index_page.add_imported_articles(
559+ self.imported_articles, self.origin)
560 return True
561
562+ def _abort_import(self, msg):
563+ logging.error('Importing of {} aborted: {}.'.format(self.origin, msg))
564+ return False
565+
566 def _read_article(self, fn, write_to, advertise, template):
567 article = self.article_class(fn, write_to, advertise, template)
568 if article.read():
569@@ -136,56 +135,17 @@
570 return False
571 article.replace_links(self.titles, self.url_map)
572 for article in self.imported_articles:
573- self.pages.extend([article.publish()])
574+ page = article.publish()
575+ self.pages.extend([page])
576+ self.urls.extend([page.get_absolute_url()])
577 if self.index_page:
578- self.index_page.publish(DEFAULT_LANG)
579- self.pages.extend([self.index_page])
580- return True
581-
582- def _create_fake_index_page(self):
583- '''Creates a fake index page at the top of the branches
584- docs namespace.'''
585-
586- if self.index_doc_url.endswith('current'):
587- redirect = '/snappy/guides'
588- else:
589- redirect = None
590- self.index_page = get_or_create_page(
591- title=self.index_doc_title, full_url=self.index_doc_url,
592- in_navigation=False, redirect=redirect, html='',
593- menu_title=None)
594- if not self.index_page:
595- return False
596- return True
597-
598- def _write_fake_index_doc(self):
599- list_pages = u''
600- for article in [a for a
601- in self.imported_articles
602- if a.full_url.startswith(self.index_doc_url)]:
603- list_pages += u'<li><a href=\"{}\">{}</a></li>'.format(
604- unicode(os.path.basename(article.full_url)),
605- article.title)
606- self.index_page.html = (
607- u'<div class=\"row\"><div class=\"eight-col\">\n'
608- '<p>This section contains documentation for the '
609- '<code>{}</code> Snappy branch.</p>'
610- '<p><ul class=\"list-ubuntu\">{}</ul></p>\n'
611- '<p>Auto-imported from <a '
612- 'href=\"{}\">{}</a>.</p>\n'
613- '</div></div>'.format(self.release_alias, list_pages,
614- self.origin, self.origin))
615-
616-
617-class SnappyRepo(Repo):
618- def __init__(self, tempdir, origin, branch_name, post_checkout_command):
619- Repo.__init__(self, tempdir, origin, branch_name,
620- post_checkout_command)
621- self.article_class = SnappyArticle
622- self.index_doc_title = 'Snappy documentation'
623-
624- def _create_fake_index_page(self):
625- self.release_alias = os.path.basename(self.index_doc_url)
626- if not self.index_doc_url.endswith('current'):
627- self.index_doc_title += ' ({})'.format(self.release_alias)
628- return Repo._create_fake_index_page(self)
629+ self.urls.extend([self.index_page.page.get_absolute_url()])
630+ return True
631+
632+ def assert_is_published(self):
633+ for page in self.pages:
634+ assert page.publisher_is_draft is False
635+ return True
636+
637+ def contains_page(self, url):
638+ return url in self.urls
639
640=== modified file 'md_importer/management/commands/import_md.py'
641--- md_importer/management/commands/import_md.py 2016-01-19 00:11:59 +0000
642+++ md_importer/management/commands/import_md.py 2016-04-18 15:28:31 +0000
643@@ -13,7 +13,7 @@
644 return
645 for branch in ExternalDocsBranch.objects.filter(
646 origin__regex=selection, active=True):
647- if not process_branch(branch):
648+ if process_branch(branch) is None:
649 break
650
651
652
653=== added file 'md_importer/migrations/0003_add_herotour_template.py'
654--- md_importer/migrations/0003_add_herotour_template.py 1970-01-01 00:00:00 +0000
655+++ md_importer/migrations/0003_add_herotour_template.py 2016-04-18 15:28:31 +0000
656@@ -0,0 +1,19 @@
657+# -*- coding: utf-8 -*-
658+from __future__ import unicode_literals
659+
660+from django.db import migrations, models
661+
662+
663+class Migration(migrations.Migration):
664+
665+ dependencies = [
666+ ('md_importer', '0002_hero_tour_changes'),
667+ ]
668+
669+ operations = [
670+ migrations.AlterField(
671+ model_name='externaldocsbranchimportdirective',
672+ name='template',
673+ field=models.CharField(default=b'default.html', help_text='Django CMS template to use for the imported articles. Default: default.html', max_length=50, choices=[(b'default.html', b'Default'), (b'landing_page.html', b'Landing Page'), (b'no_subnav.html', b'Without Subnav'), (b'with_hero.html', b'With Hero'), (b'snappy_hero_tour.html', b'Snappy Hero Tour')]),
674+ ),
675+ ]
676
677=== added file 'md_importer/migrations/0004_move_from_page_object_to_url_string.py'
678--- md_importer/migrations/0004_move_from_page_object_to_url_string.py 1970-01-01 00:00:00 +0000
679+++ md_importer/migrations/0004_move_from_page_object_to_url_string.py 2016-04-18 15:28:31 +0000
680@@ -0,0 +1,24 @@
681+# -*- coding: utf-8 -*-
682+from __future__ import unicode_literals
683+
684+from django.db import migrations, models
685+
686+
687+class Migration(migrations.Migration):
688+
689+ dependencies = [
690+ ('md_importer', '0003_add_herotour_template'),
691+ ]
692+
693+ operations = [
694+ migrations.RemoveField(
695+ model_name='importedarticle',
696+ name='page',
697+ ),
698+ migrations.AddField(
699+ model_name='importedarticle',
700+ name='url',
701+ field=models.CharField(default='imported', help_text='URL of article, e.g. snappy/guides/security', max_length=300),
702+ preserve_default=False,
703+ ),
704+ ]
705
706=== modified file 'md_importer/models.py'
707--- md_importer/models.py 2016-03-08 09:31:07 +0000
708+++ md_importer/models.py 2016-04-18 15:28:31 +0000
709@@ -2,8 +2,6 @@
710 from django.db import models
711 from django.utils.translation import ugettext_lazy as _
712
713-from cms.models import Page
714-
715
716 if settings.CMS_TEMPLATES:
717 cms_templates = settings.CMS_TEMPLATES
718@@ -71,7 +69,14 @@
719
720
721 class ImportedArticle(models.Model):
722- page = models.ForeignKey(Page)
723+ url = models.CharField(
724+ max_length=300,
725+ help_text=_('URL of article, e.g. snappy/guides/security'),
726+ )
727 branch = models.ForeignKey(ExternalDocsBranch)
728 last_import = models.DateTimeField(
729 _('Datetime'), help_text=_('Datetime of last import.'))
730+
731+ def __str__(self):
732+ return '{} -- {} -- {}'.format(
733+ self.url, self.branch, self.last_import)
734
735=== added file 'md_importer/tests/test_article.py'
736--- md_importer/tests/test_article.py 1970-01-01 00:00:00 +0000
737+++ md_importer/tests/test_article.py 2016-04-18 15:28:31 +0000
738@@ -0,0 +1,155 @@
739+import os
740+
741+from django.test import TestCase
742+
743+from md_importer.importer.article import Article
744+
745+from .utils import (
746+ db_create_root_page,
747+ db_empty_page_list,
748+ PublishedPages,
749+)
750+
751+
752+class TestArticleCreate(TestCase):
753+ def runTest(self):
754+ fn = os.path.join(
755+ os.path.dirname(__file__),
756+ 'data/snapcraft-test/docs/plugins.md')
757+ article = Article(fn, 'plugins')
758+ self.assertTrue(article.read())
759+
760+
761+class TestArticlePublish(TestCase):
762+ def runTest(self):
763+ db_empty_page_list()
764+ db_create_root_page()
765+ fn = os.path.join(
766+ os.path.dirname(__file__),
767+ 'data/snapcraft-test/docs/plugins.md')
768+ article = Article(fn, 'plugins')
769+ self.assertTrue(article.read())
770+ self.assertTrue(article.add_to_db())
771+ self.assertTrue(article.publish())
772+
773+
774+class TestArticlePublishTwiceNoHTMLChange(TestCase):
775+ def runTest(self):
776+ db_empty_page_list()
777+ db_create_root_page()
778+ fn = os.path.join(
779+ os.path.dirname(__file__),
780+ 'data/snapcraft-test/docs/plugins.md')
781+ article = Article(fn, 'plugins')
782+ self.assertTrue(article.read())
783+ self.assertTrue(article.add_to_db())
784+ self.assertTrue(article.publish())
785+ html = article.html
786+ self.assertGreater(
787+ len(html), len(open(fn).read()))
788+ self.assertTrue(article.publish())
789+ self.assertEqual(html, article.html)
790+ published_pages = PublishedPages()
791+ self.assertTrue(published_pages.has_size(1+1)) # Root + article page
792+
793+
794+class TestArticleImportTwiceNoHTMLChange(TestCase):
795+ def runTest(self):
796+ db_empty_page_list()
797+ db_create_root_page()
798+ fn = os.path.join(
799+ os.path.dirname(__file__),
800+ 'data/snapcraft-test/docs/plugins.md')
801+ article = Article(fn, 'plugins')
802+ self.assertTrue(article.read())
803+ self.assertTrue(article.add_to_db())
804+ self.assertTrue(article.publish())
805+ html = article.html
806+ self.assertGreater(
807+ len(html), len(open(fn).read()))
808+ article = Article(fn, 'plugins')
809+ self.assertTrue(article.read())
810+ self.assertTrue(article.add_to_db())
811+ self.assertTrue(article.publish())
812+ self.assertEqual(html, article.html)
813+ published_pages = PublishedPages()
814+ self.assertTrue(published_pages.has_size(1+1)) # Root + article page
815+
816+
817+class TestArticleLinkRewrite(TestCase):
818+ def runTest(self):
819+ db_empty_page_list()
820+ db_create_root_page()
821+ path = os.path.join(
822+ os.path.dirname(__file__), 'data/snapcraft-test/docs/')
823+
824+ # Read first article
825+ intro_fn = os.path.join(path, 'intro.md')
826+ intro = Article(intro_fn, 'intro')
827+ self.assertTrue(intro.read())
828+ self.assertTrue(intro.add_to_db())
829+ html = intro.html
830+
831+ # Read second article
832+ get_started_fn = os.path.join(path, 'get-started.md')
833+ get_started = Article(get_started_fn, 'get-started')
834+ self.assertTrue(get_started.read())
835+ self.assertTrue(get_started.add_to_db())
836+
837+ # Replace just one link: [get set up](get-started.md)
838+ intro.replace_links(
839+ {get_started_fn: 'get set up'},
840+ {get_started_fn: get_started})
841+ self.assertNotEqual(html, intro.html)
842+ self.assertTrue(intro.publish())
843+
844+
845+class TestArticleLinkRewriteTwice(TestCase):
846+ def runTest(self):
847+ db_empty_page_list()
848+ db_create_root_page()
849+ path = os.path.join(
850+ os.path.dirname(__file__), 'data/snapcraft-test/docs/')
851+
852+ # Read first article
853+ intro_fn = os.path.join(path, 'intro.md')
854+ intro = Article(intro_fn, 'intro')
855+ self.assertTrue(intro.read())
856+ self.assertTrue(intro.add_to_db())
857+ html = intro.html
858+
859+ # Read second article
860+ get_started_fn = os.path.join(path, 'get-started.md')
861+ get_started = Article(get_started_fn, 'get-started')
862+ self.assertTrue(get_started.read())
863+ self.assertTrue(get_started.add_to_db())
864+
865+ # Replace just one link: [get set up](get-started.md)
866+ intro.replace_links(
867+ {get_started_fn: 'get set up'},
868+ {get_started_fn: get_started})
869+ # Check if the HTML changed because of replaced links
870+ self.assertNotEqual(html, intro.html)
871+ self.assertTrue(intro.publish())
872+
873+ # Now check if the HTML will change after a second run
874+ html = intro.html
875+
876+ # 2nd time: Read first article
877+ intro = Article(intro_fn, 'intro')
878+ self.assertTrue(intro.read())
879+ self.assertTrue(intro.add_to_db())
880+
881+ # 2nd time: Read second article
882+ get_started = Article(get_started_fn, 'get-started')
883+ self.assertTrue(get_started.read())
884+ self.assertTrue(get_started.add_to_db())
885+
886+ # 2nd time: Replace just one link: [get set up](get-started.md)
887+ intro.replace_links(
888+ {get_started_fn: 'get set up'},
889+ {get_started_fn: get_started})
890+ self.assertTrue(intro.publish())
891+
892+ # After the second run, the HTML should still be the same
893+ self.assertEqual(html, intro.html)
894
895=== modified file 'md_importer/tests/test_branch_fetch.py'
896--- md_importer/tests/test_branch_fetch.py 2016-01-08 11:02:05 +0000
897+++ md_importer/tests/test_branch_fetch.py 2016-04-18 15:28:31 +0000
898@@ -4,13 +4,13 @@
899
900 from django.test import TestCase
901
902-from md_importer.importer.repo import create_repo, Repo
903+from md_importer.importer.repo import Repo
904
905
906 class TestBranchFetch(TestCase):
907 def test_git_fetch(self):
908 tempdir = tempfile.mkdtemp()
909- repo = create_repo(
910+ repo = Repo(
911 tempdir,
912 'https://github.com/ubuntu-core/snapcraft.git',
913 'master',
914@@ -22,7 +22,7 @@
915
916 def test_bzr_fetch(self):
917 tempdir = tempfile.mkdtemp()
918- repo = create_repo(
919+ repo = Repo(
920 tempdir,
921 'lp:snapcraft', # outdated, but should work for testing
922 '',
923@@ -34,7 +34,7 @@
924
925 def test_post_checkout_command(self):
926 tempdir = tempfile.mkdtemp()
927- repo = create_repo(
928+ repo = Repo(
929 tempdir,
930 'lp:snapcraft',
931 '',
932
933=== modified file 'md_importer/tests/test_branch_import.py'
934--- md_importer/tests/test_branch_import.py 2016-04-04 13:55:09 +0000
935+++ md_importer/tests/test_branch_import.py 2016-04-18 15:28:31 +0000
936@@ -10,10 +10,13 @@
937 TEMPLATE_CHOICES,
938 )
939 from md_importer.importer.article import Article
940-from md_importer.importer.publish import find_text_plugin
941+from md_importer.importer.publish import get_text_plugin
942 from md_importer.importer.tools import remove_trailing_slash
943
944-from .utils import TestLocalBranchImport
945+from .utils import (
946+ PublishedPages,
947+ TestLocalBranchImport,
948+)
949
950
951 class TestImportDirectivesBuildHierarchyImport(TestLocalBranchImport):
952@@ -50,8 +53,9 @@
953 # Make sure we got the parents right
954 for article in self.repo.imported_articles:
955 parent_url = remove_trailing_slash(
956- article.page.parent.get_absolute_url())
957- url = remove_trailing_slash(article.page.get_absolute_url())
958+ article.article_page.page.parent.get_absolute_url())
959+ url = remove_trailing_slash(
960+ article.article_page.page.get_absolute_url())
961 self.assertEqual(parent_url, os.path.split(url)[0])
962 self.assertIsInstance(article, Article)
963
964@@ -62,10 +66,11 @@
965 self.repo.add_directive('docs', '')
966 self.assertEqual(len(self.repo.directives), 1)
967 self.assertTrue(self.repo.execute_import_directives())
968- self.assertGreater(len(self.repo.imported_articles), 3)
969+ self.assertGreater(len(self.repo.imported_articles), 10)
970 self.assertTrue(self.repo.publish())
971- pages = Page.objects.all()
972- self.assertGreater(pages.count(), len(self.repo.imported_articles))
973+ published_pages = PublishedPages()
974+ self.assertTrue(published_pages.has_size(
975+ len(self.repo.imported_articles)+1)) # + landing/index page
976 for article in self.repo.imported_articles:
977 self.assertIsInstance(article, Article)
978
979@@ -78,13 +83,14 @@
980 self.repo.add_directive('HACKING.md', 'hacking')
981 self.assertEqual(len(self.repo.directives), 3)
982 self.assertTrue(self.repo.execute_import_directives())
983- self.assertGreater(len(self.repo.imported_articles), 5)
984+ self.assertGreater(len(self.repo.imported_articles), 10)
985 self.assertTrue(self.repo.publish())
986- pages = Page.objects.filter(publisher_is_draft=False)
987- self.assertEqual(pages.count(), len(self.repo.imported_articles))
988- self.assertGreater(pages.count(), 5)
989- self.assertIn(u'/en/', [p.get_absolute_url() for p in pages])
990- self.assertIn(u'/en/hacking/', [p.get_absolute_url() for p in pages])
991+ published_pages = PublishedPages()
992+ self.assertTrue(published_pages.has_size(
993+ len(self.repo.imported_articles)))
994+ self.assertTrue(published_pages.has_at_least_size(10))
995+ self.assertTrue(published_pages.contains_url(u'/en/'))
996+ self.assertTrue(published_pages.contains_url('/en/hacking/'))
997
998
999 class TestArticletreeOneFileImport(TestLocalBranchImport):
1000@@ -96,9 +102,10 @@
1001 self.assertTrue(self.repo.execute_import_directives())
1002 self.assertEqual(len(self.repo.imported_articles), 1)
1003 self.assertTrue(self.repo.publish())
1004- self.assertEqual(
1005+ published_pages = PublishedPages()
1006+ self.assertTrue(published_pages.has_size(
1007 1+1, # readme + root
1008- Page.objects.filter(publisher_is_draft=False).count())
1009+ ))
1010 self.assertEqual(self.repo.pages[0].parent, self.root)
1011
1012
1013@@ -109,7 +116,8 @@
1014 self.repo.add_directive('docs', '')
1015 self.assertTrue(self.repo.execute_import_directives())
1016 self.assertTrue(self.repo.publish())
1017- for page in Page.objects.filter(publisher_is_draft=False):
1018+ published_pages = PublishedPages()
1019+ for page in published_pages.pages:
1020 if page.parent is not None:
1021 self.assertEqual(page.parent_id, self.root.id)
1022
1023@@ -120,10 +128,11 @@
1024 self.repo.add_directive('docs', '')
1025 self.assertEqual(len(self.repo.directives), 1)
1026 self.assertTrue(self.repo.execute_import_directives())
1027- self.assertGreater(len(self.repo.imported_articles), 3)
1028+ self.assertGreater(len(self.repo.imported_articles), 10)
1029 self.assertTrue(self.repo.publish())
1030- pages = Page.objects.all()
1031- self.assertGreater(pages.count(), len(self.repo.imported_articles))
1032+ published_pages = PublishedPages()
1033+ self.assertTrue(published_pages.has_size(
1034+ len(self.repo.imported_articles)+1)) # + landing/index page
1035 for article in self.repo.imported_articles:
1036 self.assertIsInstance(article, Article)
1037 self.assertNotIn('<body>', article.html)
1038@@ -136,14 +145,15 @@
1039 self.repo.add_directive('docs', '')
1040 self.assertEqual(len(self.repo.directives), 1)
1041 self.assertTrue(self.repo.execute_import_directives())
1042- self.assertGreater(len(self.repo.imported_articles), 3)
1043+ self.assertGreater(len(self.repo.imported_articles), 10)
1044 self.assertTrue(self.repo.publish())
1045- pages = Page.objects.all()
1046- self.assertGreater(pages.count(), len(self.repo.imported_articles))
1047+ published_pages = PublishedPages()
1048+ self.assertTrue(published_pages.has_size(
1049+ len(self.repo.imported_articles)+1)) # + landing/index page
1050 for article in self.repo.imported_articles:
1051 self.assertIsInstance(article, Article)
1052 self.assertNotIn('/None/', article.full_url)
1053- for page in pages:
1054+ for page in published_pages.pages:
1055 self.assertIsNotNone(page.get_slug())
1056
1057
1058@@ -157,7 +167,8 @@
1059 for article in self.repo.imported_articles:
1060 self.assertTrue(article.advertise)
1061 self.assertTrue(self.repo.publish())
1062- for page in Page.objects.filter(publisher_is_draft=False):
1063+ published_pages = PublishedPages()
1064+ for page in published_pages.pages:
1065 if page.parent is not None:
1066 parent = page.parent.get_public_object()
1067 self.assertEqual(parent.id, self.root.id)
1068@@ -174,7 +185,8 @@
1069 for article in self.repo.imported_articles:
1070 self.assertFalse(article.advertise)
1071 self.assertTrue(self.repo.publish())
1072- for page in Page.objects.filter(publisher_is_draft=False):
1073+ published_pages = PublishedPages()
1074+ for page in published_pages.pages:
1075 if page.parent is not None:
1076 self.assertEqual(page.parent_id, self.root.id)
1077 self.assertFalse(page.in_navigation)
1078@@ -188,9 +200,9 @@
1079 self.repo.add_directive('docs', '')
1080 self.assertTrue(self.repo.execute_import_directives())
1081 self.assertTrue(self.repo.publish())
1082- self.assertEqual(
1083- Page.objects.filter(publisher_is_draft=False).count(),
1084- len(self.repo.imported_articles)+1) # articles + root
1085+ published_pages = PublishedPages()
1086+ self.assertTrue(published_pages.has_size(
1087+ len(self.repo.imported_articles)+1)) # articles + root
1088 # Run second import
1089 shutil.rmtree(self.tempdir)
1090 self.create_repo('data/snapcraft-test')
1091@@ -199,9 +211,9 @@
1092 self.assertEqual(len(self.repo.imported_articles), 0)
1093 self.assertTrue(self.repo.execute_import_directives())
1094 self.assertTrue(self.repo.publish())
1095- self.assertEqual(
1096- Page.objects.filter(publisher_is_draft=False).count(),
1097- len(self.repo.imported_articles)+1) # articles + root
1098+ published_pages = PublishedPages()
1099+ self.assertTrue(published_pages.has_size(
1100+ len(self.repo.imported_articles)+1)) # articles + root
1101
1102
1103 class TestTwiceImportNoHtmlChange(TestLocalBranchImport):
1104@@ -212,9 +224,9 @@
1105 self.repo.add_directive('docs', '')
1106 self.assertTrue(self.repo.execute_import_directives())
1107 self.assertTrue(self.repo.publish())
1108- self.assertEqual(
1109- Page.objects.filter(publisher_is_draft=False).count(),
1110- len(self.repo.imported_articles)+1) # articles + root
1111+ published_pages = PublishedPages()
1112+ self.assertTrue(published_pages.has_size(
1113+ len(self.repo.imported_articles)+1)) # articles + root
1114 shutil.rmtree(self.tempdir)
1115 # Take the time before publishing the second import
1116 now = datetime.now(pytz.utc)
1117@@ -226,9 +238,10 @@
1118 self.assertTrue(self.repo.execute_import_directives())
1119 self.assertTrue(self.repo.publish())
1120 # Check the page's plugins
1121- for page in Page.objects.filter(publisher_is_draft=False):
1122+ published_pages.update()
1123+ for page in published_pages.pages:
1124 if page != self.root:
1125- (dummy, plugin) = find_text_plugin(page)
1126+ (dummy, plugin) = get_text_plugin(page)
1127 self.assertGreater(now, plugin.changed_date)
1128
1129
1130@@ -241,7 +254,8 @@
1131 for article in self.repo.imported_articles:
1132 self.assertEqual(article.template, DEFAULT_TEMPLATE)
1133 self.assertTrue(self.repo.publish())
1134- for page in Page.objects.filter(publisher_is_draft=False):
1135+ published_pages = PublishedPages()
1136+ for page in published_pages.pages:
1137 if page.parent is not None:
1138 self.assertEqual(page.template, DEFAULT_TEMPLATE)
1139
1140@@ -256,6 +270,7 @@
1141 for article in self.repo.imported_articles:
1142 self.assertEqual(article.template, template_to_use)
1143 self.assertTrue(self.repo.publish())
1144- for page in Page.objects.filter(publisher_is_draft=False):
1145+ published_pages = PublishedPages()
1146+ for page in published_pages.pages:
1147 if page.parent is not None:
1148 self.assertEqual(page.template, template_to_use)
1149
1150=== modified file 'md_importer/tests/test_import_process.py'
1151--- md_importer/tests/test_import_process.py 2016-01-16 00:36:39 +0000
1152+++ md_importer/tests/test_import_process.py 2016-04-18 15:28:31 +0000
1153@@ -4,6 +4,7 @@
1154 from cms.api import publish_pages
1155 from cms.models import Page
1156
1157+from md_importer.importer import DEFAULT_LANG
1158 from md_importer.importer.process import process_branch
1159 from md_importer.models import (
1160 ExternalDocsBranch,
1161@@ -11,9 +12,12 @@
1162 ImportedArticle,
1163 )
1164 from .utils import (
1165+ check_repo,
1166+ check_imported_article,
1167 db_add_empty_page,
1168 db_create_root_page,
1169 db_empty_page_list,
1170+ PublishedPages,
1171 )
1172
1173
1174@@ -41,7 +45,36 @@
1175 import_from='HACKING.md',
1176 write_to='snappy/build-apps/devel/hacking',
1177 external_docs_branch=branch)
1178- self.assertTrue(process_branch(branch))
1179+ self.assertIsNotNone(process_branch(branch))
1180+
1181+
1182+class TestPageStateAfterImportProcess(TestCase):
1183+ def runTest(self):
1184+ db_empty_page_list()
1185+ root = db_create_root_page()
1186+ snappy_page = db_add_empty_page('Snappy', root)
1187+ build_apps = db_add_empty_page('Build Apps', snappy_page)
1188+ publish_pages([snappy_page, build_apps])
1189+ ExternalDocsBranch.objects.all().delete()
1190+ ExternalDocsBranchImportDirective.objects.all().delete()
1191+ ImportedArticle.objects.all().delete()
1192+ branch, created = ExternalDocsBranch.objects.get_or_create(
1193+ origin=os.path.join(
1194+ os.path.dirname(__file__), 'data/snapcraft-test'),
1195+ branch_name='')
1196+ a, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1197+ import_from='README.md', write_to='snappy/build-apps/devel',
1198+ external_docs_branch=branch)
1199+ b, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1200+ import_from='docs', write_to='snappy/build-apps/devel',
1201+ external_docs_branch=branch)
1202+ c, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1203+ import_from='HACKING.md',
1204+ write_to='snappy/build-apps/devel/hacking',
1205+ external_docs_branch=branch)
1206+ self.assertIsNotNone(process_branch(branch))
1207+ for imported_article in ImportedArticle.objects.all():
1208+ self.assertTrue(check_imported_article(imported_article))
1209
1210
1211 class TestImportProcessBranchWhichChangesFiles(TestCase):
1212@@ -57,12 +90,241 @@
1213 branch_name='')
1214 a, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1215 import_from='', write_to='', external_docs_branch=branch)
1216- self.assertTrue(process_branch(branch))
1217- self.assertEqual(
1218- Page.objects.filter(publisher_is_draft=False).count(), 3)
1219+ self.assertIsNotNone(process_branch(branch))
1220+ published_pages = PublishedPages()
1221+ self.assertTrue(published_pages.has_size(3))
1222 branch.origin = os.path.join(
1223 os.path.dirname(__file__), 'data/link2-test')
1224 branch.save()
1225 self.assertTrue(process_branch(branch))
1226- self.assertEqual(
1227- Page.objects.filter(publisher_is_draft=False).count(), 3)
1228+ published_pages.update()
1229+ self.assertTrue(published_pages.has_size(3))
1230+
1231+
1232+class TestImportProcessTwice(TestCase):
1233+ '''
1234+ This is a pretty standard snapcraft import. snappy/build-apps are
1235+ already created. Running the import twice used to create problems,
1236+ because the snappy/build-apps used to be deleted at the end of
1237+ process.process_branch. This test will make sure this will never
1238+ happen again.
1239+ '''
1240+ def runTest(self):
1241+ db_empty_page_list()
1242+ root = db_create_root_page()
1243+ snappy_page = db_add_empty_page('Snappy', root)
1244+ build_apps = db_add_empty_page(
1245+ 'Build Apps', snappy_page, slug='build-apps')
1246+ publish_pages([snappy_page, build_apps])
1247+ ExternalDocsBranch.objects.all().delete()
1248+ ExternalDocsBranchImportDirective.objects.all().delete()
1249+ ImportedArticle.objects.all().delete()
1250+ branch, created = ExternalDocsBranch.objects.get_or_create(
1251+ origin=os.path.join(
1252+ os.path.dirname(__file__), 'data/snapcraft-test'),
1253+ branch_name='')
1254+ a, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1255+ import_from='docs/intro.md', write_to='snappy/build-apps',
1256+ external_docs_branch=branch)
1257+ b, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1258+ import_from='docs', write_to='snappy/build-apps',
1259+ external_docs_branch=branch)
1260+ repo = process_branch(branch)
1261+ self.assertTrue(check_repo(repo))
1262+ self.assertGreater(len(repo.pages), 10)
1263+ self.assertTrue(repo.contains_page(
1264+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1265+ published_pages = PublishedPages()
1266+ self.assertTrue(published_pages.contains_url(
1267+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1268+ self.assertTrue(published_pages.has_at_least_size(10))
1269+ for imported_article in ImportedArticle.objects.all():
1270+ self.assertTrue(check_imported_article(imported_article))
1271+
1272+ # Run the import a second time
1273+ repo = process_branch(branch)
1274+ self.assertTrue(check_repo(repo))
1275+ self.assertGreater(len(repo.pages), 10)
1276+ self.assertTrue(repo.contains_page(
1277+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1278+ published_pages.update()
1279+ self.assertTrue(published_pages.contains_url(
1280+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1281+ self.assertTrue(published_pages.has_at_least_size(10))
1282+ for imported_article in ImportedArticle.objects.all():
1283+ self.assertTrue(check_imported_article(imported_article))
1284+
1285+
1286+class TestWholeImportProcessTwiceVariantA(TestCase):
1287+ '''
1288+ This is a pretty standard snapcraft import. snappy/build-apps are
1289+ already created. Running the import twice used to create problems,
1290+ because the snappy/build-apps used to be deleted at the end of
1291+ process.process_branch. This test will make sure this will never
1292+ happen again.
1293+ This time we test a whole import, ie Snappy + Snapcraft twice.
1294+ '''
1295+ def runTest(self):
1296+ db_empty_page_list()
1297+ self.assertEqual(Page.objects.count(), 0)
1298+ root = db_create_root_page()
1299+ snappy_page = db_add_empty_page('Snappy', root)
1300+ build_apps = db_add_empty_page(
1301+ 'Build Apps', snappy_page, slug='build-apps')
1302+ guides = db_add_empty_page('Guides', snappy_page)
1303+ phone = db_add_empty_page('Phone', root)
1304+ publish_pages([snappy_page, build_apps, guides, phone])
1305+ published_pages = PublishedPages()
1306+ self.assertTrue(published_pages.has_size(5))
1307+ ExternalDocsBranch.objects.all().delete()
1308+ ExternalDocsBranchImportDirective.objects.all().delete()
1309+ ImportedArticle.objects.all().delete()
1310+
1311+ # Snapcraft import definition
1312+ snapcraft_branch, created = ExternalDocsBranch.objects.get_or_create(
1313+ origin=os.path.join(
1314+ os.path.dirname(__file__), 'data/snapcraft-test'),
1315+ branch_name='')
1316+ a, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1317+ import_from='docs/intro.md', write_to='snappy/build-apps',
1318+ external_docs_branch=snapcraft_branch)
1319+ b, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1320+ import_from='docs', write_to='snappy/build-apps',
1321+ external_docs_branch=snapcraft_branch)
1322+
1323+ # Snappy import definition
1324+ snappy_branch, created = ExternalDocsBranch.objects.get_or_create(
1325+ origin=os.path.join(
1326+ os.path.dirname(__file__), 'data/snappy-test'),
1327+ branch_name='')
1328+ c, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1329+ import_from='docs', write_to='snappy/guides',
1330+ external_docs_branch=snappy_branch)
1331+
1332+ # Run the import a first time
1333+ snapcraft_repo = process_branch(snapcraft_branch)
1334+ self.assertTrue(check_repo(snapcraft_repo))
1335+ self.assertGreater(len(snapcraft_repo.pages), 10)
1336+ self.assertTrue(snapcraft_repo.contains_page(
1337+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1338+ snappy_repo = process_branch(snappy_branch)
1339+ self.assertTrue(check_repo(snappy_repo))
1340+ self.assertGreater(len(snappy_repo.pages), 10)
1341+ self.assertTrue(snappy_repo.contains_page(
1342+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1343+
1344+ published_pages = PublishedPages()
1345+ self.assertTrue(published_pages.contains_url(
1346+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1347+ self.assertTrue(published_pages.contains_url(
1348+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1349+ self.assertTrue(published_pages.has_at_least_size(20))
1350+ for imported_article in ImportedArticle.objects.all():
1351+ self.assertTrue(check_imported_article(imported_article))
1352+
1353+ # Run the import a second time
1354+ snapcraft_repo = process_branch(snapcraft_branch)
1355+ self.assertTrue(check_repo(snapcraft_repo))
1356+ self.assertGreater(len(snapcraft_repo.pages), 10)
1357+ self.assertTrue(snapcraft_repo.contains_page(
1358+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1359+ snappy_repo = process_branch(snappy_branch)
1360+ self.assertTrue(check_repo(snappy_repo))
1361+ self.assertGreater(len(snappy_repo.pages), 10)
1362+ self.assertTrue(snappy_repo.contains_page(
1363+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1364+
1365+ published_pages.update()
1366+ self.assertTrue(published_pages.contains_url(
1367+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1368+ self.assertTrue(published_pages.contains_url(
1369+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1370+ self.assertTrue(published_pages.has_at_least_size(20))
1371+ for imported_article in ImportedArticle.objects.all():
1372+ self.assertTrue(check_imported_article(imported_article))
1373+
1374+
1375+class TestWholeImportProcessTwiceVariantB(TestCase):
1376+ '''
1377+ This is a pretty standard snapcraft import. snappy/build-apps are
1378+ already created. Running the import twice used to create problems,
1379+ because the snappy/build-apps used to be deleted at the end of
1380+ process.process_branch. This test will make sure this will never
1381+ happen again.
1382+ This time we test a whole import, ie Snappy + Snapcraft twice.
1383+ '''
1384+ def runTest(self):
1385+ db_empty_page_list()
1386+ self.assertEqual(Page.objects.count(), 0)
1387+ root = db_create_root_page()
1388+ snappy_page = db_add_empty_page('Snappy', root)
1389+ guides = db_add_empty_page('Guides', snappy_page)
1390+ publish_pages([snappy_page, guides])
1391+ published_pages = PublishedPages()
1392+ self.assertTrue(published_pages.has_size(3))
1393+ ExternalDocsBranch.objects.all().delete()
1394+ ExternalDocsBranchImportDirective.objects.all().delete()
1395+ ImportedArticle.objects.all().delete()
1396+
1397+ # Snapcraft import definition
1398+ snapcraft_branch, created = ExternalDocsBranch.objects.get_or_create(
1399+ origin=os.path.join(
1400+ os.path.dirname(__file__), 'data/snapcraft-test'),
1401+ branch_name='')
1402+ a, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1403+ import_from='docs/intro.md', write_to='snappy/build-apps',
1404+ external_docs_branch=snapcraft_branch)
1405+ b, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1406+ import_from='docs', write_to='snappy/build-apps',
1407+ external_docs_branch=snapcraft_branch)
1408+
1409+ # Snappy import definition
1410+ snappy_branch, created = ExternalDocsBranch.objects.get_or_create(
1411+ origin=os.path.join(
1412+ os.path.dirname(__file__), 'data/snappy-test'),
1413+ branch_name='')
1414+ c, created = ExternalDocsBranchImportDirective.objects.get_or_create(
1415+ import_from='docs', write_to='snappy/guides',
1416+ external_docs_branch=snappy_branch)
1417+
1418+ # Run the import a first time
1419+ snapcraft_repo = process_branch(snapcraft_branch)
1420+ self.assertTrue(check_repo(snapcraft_repo))
1421+ self.assertGreater(len(snapcraft_repo.pages), 10)
1422+ self.assertTrue(snapcraft_repo.contains_page(
1423+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1424+ snappy_repo = process_branch(snappy_branch)
1425+ self.assertTrue(check_repo(snappy_repo))
1426+ self.assertGreater(len(snappy_repo.pages), 10)
1427+ self.assertTrue(snappy_repo.contains_page(
1428+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1429+
1430+ published_pages = PublishedPages()
1431+ self.assertTrue(published_pages.contains_url(
1432+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1433+ self.assertTrue(published_pages.contains_url(
1434+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1435+ self.assertTrue(published_pages.has_at_least_size(20))
1436+ for imported_article in ImportedArticle.objects.all():
1437+ self.assertTrue(check_imported_article(imported_article))
1438+
1439+ # Run the import a second time
1440+ snapcraft_repo = process_branch(snapcraft_branch)
1441+ self.assertTrue(check_repo(snapcraft_repo))
1442+ self.assertGreater(len(snapcraft_repo.pages), 10)
1443+ self.assertTrue(snapcraft_repo.contains_page(
1444+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1445+ snappy_repo = process_branch(snappy_branch)
1446+ self.assertTrue(check_repo(snappy_repo))
1447+ self.assertGreater(len(snappy_repo.pages), 10)
1448+ self.assertTrue(snappy_repo.contains_page(
1449+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1450+
1451+ published_pages.update()
1452+ self.assertTrue(published_pages.contains_url(
1453+ '/{}/snappy/build-apps/'.format(DEFAULT_LANG)))
1454+ self.assertTrue(published_pages.contains_url(
1455+ '/{}/snappy/guides/'.format(DEFAULT_LANG)))
1456+ self.assertTrue(published_pages.has_at_least_size(20))
1457+ for imported_article in ImportedArticle.objects.all():
1458+ self.assertTrue(check_imported_article(imported_article))
1459
1460=== modified file 'md_importer/tests/test_link_rewrite.py'
1461--- md_importer/tests/test_link_rewrite.py 2016-03-22 10:52:47 +0000
1462+++ md_importer/tests/test_link_rewrite.py 2016-04-18 15:28:31 +0000
1463@@ -7,6 +7,7 @@
1464 from .utils import (
1465 db_add_empty_page,
1466 is_local_link,
1467+ PublishedPages,
1468 TestLocalBranchImport,
1469 )
1470
1471@@ -17,11 +18,11 @@
1472 self.repo.add_directive('', '')
1473 self.assertTrue(self.repo.execute_import_directives())
1474 self.assertTrue(self.repo.publish())
1475- pages = Page.objects.filter(publisher_is_draft=False)
1476- self.assertEqual(pages.count(), 1+2) # root + 2 articles
1477+ published_pages = PublishedPages()
1478+ self.assertTrue(published_pages.has_size(1+2)) # root + 2 articles
1479 for article in self.repo.imported_articles:
1480 self.assertTrue(isinstance(article, Article))
1481- self.assertEqual(article.page.parent, self.root)
1482+ self.assertEqual(article.article_page.page.parent, self.root)
1483 soup = BeautifulSoup(article.html, 'html5lib')
1484 for link in soup.find_all('a'):
1485 page = self.check_local_link(link.attrs['href'])
1486@@ -29,8 +30,8 @@
1487 page,
1488 msg='Link {} not found. Available pages: {}'.format(
1489 link.attrs['href'],
1490- ', '.join([p.get_absolute_url() for p in pages])))
1491- self.assertIn(page, pages)
1492+ ', '.join(published_pages.urls)))
1493+ self.assertIn(page, published_pages.pages)
1494 if article.slug == 'file1':
1495 for link in soup.find_all('a'):
1496 if not link.has_attr('class') or \
1497@@ -46,18 +47,18 @@
1498 self.repo.add_directive('', '')
1499 self.assertTrue(self.repo.execute_import_directives())
1500 self.assertTrue(self.repo.publish())
1501- pages = Page.objects.filter(publisher_is_draft=False)
1502- self.assertEqual(pages.count(), 1+2) # root + 2 articles
1503+ published_pages = PublishedPages()
1504+ self.assertTrue(published_pages.has_size(1+2)) # root + 2 articles
1505 for article in self.repo.imported_articles:
1506 self.assertTrue(isinstance(article, Article))
1507- self.assertEqual(article.page.parent, self.root)
1508+ self.assertEqual(article.article_page.page.parent, self.root)
1509 soup = BeautifulSoup(article.html, 'html5lib')
1510 for link in soup.find_all('a'):
1511 if not link.has_attr('class') or \
1512 'headeranchor-link' not in link.attrs['class']:
1513 page = self.check_local_link(link.attrs['href'])
1514 self.assertIsNone(page)
1515- self.assertNotIn(page, pages)
1516+ self.assertNotIn(page, published_pages.pages)
1517
1518
1519 class TestNoneNotInLinks(TestLocalBranchImport):
1520@@ -67,8 +68,8 @@
1521 self.assertFalse(snappy_page.publisher_is_draft)
1522 build_apps = db_add_empty_page('Build Apps', snappy_page)
1523 self.assertFalse(build_apps.publisher_is_draft)
1524- self.assertEqual(
1525- 3, Page.objects.filter(publisher_is_draft=False).count())
1526+ published_pages = PublishedPages()
1527+ self.assertTrue(published_pages.has_size(3))
1528 self.repo.add_directive('docs/intro.md', 'snappy/build-apps/current')
1529 self.repo.add_directive('docs', 'snappy/build-apps/current')
1530 self.assertTrue(self.repo.execute_import_directives())
1531@@ -89,8 +90,8 @@
1532 self.assertFalse(snappy_page.publisher_is_draft)
1533 build_apps = db_add_empty_page('Build Apps', snappy_page)
1534 self.assertFalse(build_apps.publisher_is_draft)
1535- self.assertEqual(
1536- 3, Page.objects.filter(publisher_is_draft=False).count())
1537+ published_pages = PublishedPages()
1538+ self.assertTrue(published_pages.has_size(3))
1539 self.repo.add_directive('docs/intro.md', 'snappy/build-apps/current')
1540 self.repo.add_directive('docs', 'snappy/build-apps/current')
1541 self.assertTrue(self.repo.execute_import_directives())
1542
1543=== modified file 'md_importer/tests/test_misc.py'
1544--- md_importer/tests/test_misc.py 2016-01-15 14:07:21 +0000
1545+++ md_importer/tests/test_misc.py 2016-04-18 15:28:31 +0000
1546@@ -1,8 +1,7 @@
1547 from bs4 import BeautifulSoup
1548
1549-from cms.models import Page
1550-
1551 from .utils import (
1552+ PublishedPages,
1553 TestLocalBranchImport,
1554 )
1555
1556@@ -20,10 +19,10 @@
1557 self.repo.add_directive('', '')
1558 self.assertTrue(self.repo.execute_import_directives())
1559 self.assertTrue(self.repo.publish())
1560- pages = Page.objects.filter(publisher_is_draft=False)
1561- self.assertEqual(pages.count(), 1+1) # root + 1 article
1562+ published_pages = PublishedPages()
1563+ self.assertTrue(published_pages.has_size(1+1)) # root + 1 article
1564 for article in self.repo.imported_articles:
1565- self.assertEqual(article.page.parent, self.root)
1566+ self.assertEqual(article.article_page.page.parent, self.root)
1567 soup = BeautifulSoup(article.html, 'html5lib')
1568 for link in soup.find_all('a'):
1569 page = self.check_local_link(link.attrs['href'])
1570@@ -31,5 +30,5 @@
1571 page,
1572 msg='Link {} not found. Available pages: {}'.format(
1573 link.attrs['href'],
1574- ', '.join([p.get_absolute_url() for p in pages])))
1575- self.assertIn(page, pages)
1576+ ', '.join(published_pages.urls)))
1577+ self.assertIn(page, published_pages.pages)
1578
1579=== modified file 'md_importer/tests/test_snappy_import.py'
1580--- md_importer/tests/test_snappy_import.py 2016-01-11 14:02:04 +0000
1581+++ md_importer/tests/test_snappy_import.py 2016-04-18 15:28:31 +0000
1582@@ -1,11 +1,11 @@
1583 from cms.api import publish_pages
1584 from cms.models import Page
1585
1586-from md_importer.importer import DEFAULT_LANG
1587-from md_importer.importer.repo import SnappyRepo
1588-from md_importer.importer.article import SnappyArticle
1589+from md_importer.importer.repo import Repo
1590+from md_importer.importer.article import Article
1591 from .utils import (
1592 db_add_empty_page,
1593+ PublishedPages,
1594 TestLocalBranchImport,
1595 )
1596
1597@@ -16,46 +16,16 @@
1598 snappy_page = db_add_empty_page('Snappy', self.root)
1599 guides = db_add_empty_page('Guides', snappy_page)
1600 publish_pages([snappy_page, guides])
1601- self.assertTrue(isinstance(self.repo, SnappyRepo))
1602+ self.assertTrue(isinstance(self.repo, Repo))
1603 self.repo.add_directive('docs', 'snappy/guides/devel')
1604 self.assertTrue(self.repo.execute_import_directives())
1605 self.assertTrue(self.repo.publish())
1606 for article in self.repo.imported_articles:
1607- self.assertTrue(isinstance(article, SnappyArticle))
1608+ self.assertTrue(isinstance(article, Article))
1609 self.assertGreater(len(self.repo.pages), 0)
1610 devel = Page.objects.filter(parent=guides.get_public_object())
1611 self.assertEqual(devel.count(), 1)
1612- for page in Page.objects.filter(publisher_is_draft=False):
1613+ published_pages = PublishedPages()
1614+ for page in published_pages.pages:
1615 if page not in [self.root, snappy_page, guides, devel[0]]:
1616 self.assertEqual(page.parent, devel[0])
1617-
1618-
1619-class TestSnappyCurrentImport(TestLocalBranchImport):
1620- def runTest(self):
1621- self.create_repo('data/snappy-test')
1622- snappy_page = db_add_empty_page('Snappy', self.root)
1623- guides = db_add_empty_page('Guides', snappy_page)
1624- publish_pages([snappy_page, guides])
1625- self.assertTrue(isinstance(self.repo, SnappyRepo))
1626- self.repo.add_directive('docs', 'snappy/guides/current')
1627- self.assertTrue(self.repo.execute_import_directives())
1628- self.assertTrue(self.repo.publish())
1629- number_of_articles = len(self.repo.imported_articles)
1630- for article in self.repo.imported_articles:
1631- self.assertTrue(isinstance(article, SnappyArticle))
1632- self.assertGreater(number_of_articles, 0)
1633- pages = Page.objects.filter(publisher_is_draft=False)
1634- current_search = [
1635- a for a in pages
1636- if a.get_slug('current') and
1637- a.get_absolute_url().endswith('snappy/guides/current/')]
1638- self.assertEqual(len(current_search), 1)
1639- current = current_search[0]
1640- nav_pages = [self.root, snappy_page, guides, current]
1641- self.assertEqual(
1642- number_of_articles, pages.count()-len(nav_pages))
1643- for page in [a for a in pages if a not in nav_pages]:
1644- if page.get_redirect(DEFAULT_LANG):
1645- self.assertEqual(page.parent, guides)
1646- else:
1647- self.assertEqual(page.parent, current)
1648
1649=== modified file 'md_importer/tests/test_utils.py'
1650--- md_importer/tests/test_utils.py 2016-01-11 14:02:04 +0000
1651+++ md_importer/tests/test_utils.py 2016-04-18 15:28:31 +0000
1652@@ -8,6 +8,7 @@
1653 db_add_empty_page,
1654 db_create_root_page,
1655 db_empty_page_list,
1656+ PublishedPages,
1657 TestLocalBranchImport,
1658 )
1659
1660@@ -22,8 +23,8 @@
1661 root = db_create_root_page()
1662 self.assertNotEqual(root, None)
1663 self.assertFalse(root.publisher_is_draft)
1664- self.assertEqual(
1665- Page.objects.filter(publisher_is_draft=False).count(), 1)
1666+ published_pages = PublishedPages()
1667+ self.assertTrue(published_pages.has_size(1))
1668
1669 def test_simple_articletree(self):
1670 db_empty_page_list()
1671@@ -33,8 +34,8 @@
1672 self.assertFalse(snappy.publisher_is_draft)
1673 guides = db_add_empty_page('Guides', snappy)
1674 self.assertFalse(guides.publisher_is_draft)
1675- self.assertEqual(
1676- Page.objects.filter(publisher_is_draft=False).count(), 3)
1677+ published_pages = PublishedPages()
1678+ self.assertTrue(published_pages.has_size(3))
1679 self.assertEqual(guides.parent.get_public_object(), snappy)
1680 self.assertEqual(snappy.parent.get_public_object(), root)
1681
1682
1683=== modified file 'md_importer/tests/test_website_import.py'
1684--- md_importer/tests/test_website_import.py 2016-04-04 09:04:22 +0000
1685+++ md_importer/tests/test_website_import.py 2016-04-18 15:28:31 +0000
1686@@ -2,11 +2,11 @@
1687 from md_importer.importer.repo import Repo
1688 from .utils import (
1689 db_add_empty_page,
1690+ PublishedPages,
1691 TestLocalBranchImport,
1692 )
1693
1694 from cms.api import add_plugin, publish_pages
1695-from cms.models import Page
1696
1697
1698 class TestSnappyWebsiteRead(TestLocalBranchImport):
1699@@ -44,7 +44,7 @@
1700 self.assertTrue(self.repo.execute_import_directives())
1701 self.assertTrue(self.repo.publish())
1702 self.assertGreater(len(self.repo.pages), 10)
1703- pages = Page.objects.filter(publisher_is_draft=False)
1704+ published_pages = PublishedPages()
1705 expected_urls = [
1706 '/en/',
1707 '/en/snappy/',
1708@@ -85,6 +85,6 @@
1709 '/en/snappy/start/as-dev/16-04/step4-first-snap/',
1710 '/en/snappy/start/as-dev/16-04/step5-further-readings/',
1711 ]
1712- self.assertEqual(len(expected_urls), len(pages))
1713+ self.assertTrue(published_pages.has_size(len(expected_urls)))
1714 for url in expected_urls:
1715- self.assertTrue(url in [p.get_absolute_url() for p in pages])
1716+ self.assertTrue(published_pages.contains_url(url))
1717
1718=== modified file 'md_importer/tests/utils.py'
1719--- md_importer/tests/utils.py 2016-03-09 15:42:41 +0000
1720+++ md_importer/tests/utils.py 2016-04-18 15:28:31 +0000
1721@@ -10,8 +10,11 @@
1722 from cms.test_utils.testcases import CMSTestCase
1723 from cms.utils.page_resolver import get_page_from_request
1724
1725-from ..importer import DEFAULT_LANG
1726-from ..importer.repo import create_repo
1727+from md_importer.models import ImportedArticle
1728+from ..importer import (
1729+ DEFAULT_LANG,
1730+)
1731+from ..importer.repo import Repo
1732
1733 if sys.version_info.major == 2:
1734 from urlparse import urlparse
1735@@ -52,7 +55,7 @@
1736 def create_repo(self, docs_path):
1737 origin = os.path.join(os.path.dirname(__file__), docs_path)
1738 self.assertTrue(os.path.exists(origin))
1739- self.repo = create_repo(self.tempdir, origin, '', '')
1740+ self.repo = Repo(self.tempdir, origin, '', '')
1741 self.fetch_retcode = self.repo.get()
1742 self.assertEqual(self.fetch_retcode, 0)
1743
1744@@ -69,6 +72,18 @@
1745 shutil.rmtree(self.tempdir)
1746
1747
1748+def check_imported_article(imported_article):
1749+ assert imported_article is not None
1750+ assert isinstance(imported_article, ImportedArticle)
1751+ return True
1752+
1753+
1754+def check_repo(repo):
1755+ assert repo is not None
1756+ assert isinstance(repo, Repo)
1757+ return repo.assert_is_published()
1758+
1759+
1760 def is_local_link(link):
1761 if link.has_attr('class') and \
1762 'headeranchor-link' in link.attrs['class']:
1763@@ -78,3 +93,22 @@
1764 if scheme in ['http', 'https', 'mailto']:
1765 return False
1766 return True
1767+
1768+
1769+class PublishedPages:
1770+ def __init__(self):
1771+ self.pages = None
1772+ self.update()
1773+
1774+ def update(self):
1775+ self.pages = Page.objects.filter(publisher_is_draft=False)
1776+ self.urls = [p.get_absolute_url() for p in self.pages]
1777+
1778+ def contains_url(self, url):
1779+ return url in self.urls
1780+
1781+ def has_size(self, size):
1782+ return self.pages.count() == size
1783+
1784+ def has_at_least_size(self, size):
1785+ return self.pages.count() >= size

Subscribers

People subscribed via source and target branches