class ShowPostsMacroTest(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True, enable=('trac_wiki_blog.*', 'tractags.*', 'trac.*'))
        self.env.upgrade()
        self.macro = ShowPostsMacro(self.env)
    
    def tearDown(self):
        self.env.destroy_temp_directory()
    
    def req(self):
        req = mock_request('/')
        req.populate(self.env)
        return req
    
    def _expand_macro(self, argument_string=''):
        formatter = Mock(req=self.req())
        html = self.macro.expand_macro(formatter, 'ShowPosts', argument_string)
        return html
    
    # --------------------------------------------------------------------------
    # Macro Title
    
    def _title_from_html(self, html):
        soup = BeautifulSoup(html)
        title_element = soup.find(name='h1', attrs={'class': 'blog_heading'})
        return title_element.string
    
    def test_has_default_title(self):
        title = self._title_from_html(self._expand_macro())
        assert_equals('Blog Posts', title)
    
    def test_can_set_custom_title(self):
        title = self._title_from_html(self._expand_macro(u'title=Latest…'))
        assert_equals(u'Latest…', title)
    
    def test_strips_spaces_from_macro_title(self):
        title = self._title_from_html(self._expand_macro(u'title= A Title '))
        assert_equals(u'A Title', title)

    # --------------------------------------------------------------------------
    # Relative attachment links
    
    def _has_permission(self, username, action):
        from trac.perm import DefaultPermissionPolicy, PermissionSystem
        DefaultPermissionPolicy(self.env).permission_cache = {}
        return action in PermissionSystem(self.env).get_user_permissions(username)
    
    def _grant_permission(self, username, action):
        from trac.perm import DefaultPermissionPolicy, PermissionSystem
        if self._has_permission(username, action):
            return
        DefaultPermissionPolicy(self.env).permission_cache = {}
        PermissionSystem(self.env).grant_permission(username, action)
        assert self._has_permission(username, action)
    
    def _add_attachment(self, parent_resource, filename):
        attachment = Attachment(self.env, parent_resource.child('attachment', None))
        attachment_fp = StringIO('some content')
        attachment.insert(filename, attachment_fp, len(attachment_fp.getvalue()))
        return attachment
    
    def test_can_resolve_relative_attachment_links_correclty(self):
        self.env.use_temp_directory()
        # Need to import so that WIKI_* permissions are known
        from trac.wiki.web_ui import WikiModule
        self._grant_permission('anonymous', 'TRAC_ADMIN')
        
        page = create_tagged_page(self.env, self.req(), 'Foo', '= Foo =\n[attachment:test.txt]', ('blog',))
        page.save(None, None, '127.0.0.1')
        self._add_attachment(page.resource, 'test.txt')

        html = self._expand_macro()
        attachment_link = BeautifulSoup(html).find(name='a', text='test.txt').parent
        assert_equals('attachment', attachment_link['class'])

    # --------------------------------------------------------------------------
    # Blog Post Titles
    
    def test_title_is_only_shown_once(self):
        self._grant_permission('anonymous', 'TRAC_ADMIN')
        page = create_tagged_page(self.env, self.req(), 'Foo', '= SomeTitle =\ncontent', ('blog',))
        page.save(None, None, '127.0.0.1')
        
        soup = BeautifulSoup(self._expand_macro())
        plain_text = ''.join(soup.div(text=True))
        # looking in plain text (with all tags stripped) as Trac will add the 
        # title also in the dom node id and an anchor to link to that heading
        matches = re.findall('SomeTitle', plain_text)
        assert_length(1, matches)
    
    def test_can_use_wiki_text_in_page_title(self):
        self._grant_permission('anonymous', 'TRAC_ADMIN')
        page = create_tagged_page(self.env, self.req(), 'Foo', "= Some ''italic'' Title =\ncontent", ('blog',))
        page.save(None, None, '127.0.0.1')
        
        title_link = BeautifulSoup(self._expand_macro()).find('a', href='/wiki/Foo')
        assert_contains('Some <i>italic</i> Title', unicode(title_link))
    
    def test_post_title_contains_link_to_blog_post_page(self):
        self._grant_permission('anonymous', 'TRAC_ADMIN')
        page = create_tagged_page(self.env, self.req(), 'Foo', "= Some Title =\ncontent", ('blog',))
        page.save(None, None, '127.0.0.1')
        
        html = self._expand_macro()
        post_heading = BeautifulSoup(html).find('h1', id='SomeTitle')
        post_link = post_heading.find('a', href='/wiki/Foo')
        assert_not_none(post_link)
        assert_equals('Some Title', post_link.text)
class NewBlogPostTest(TracTest):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True, enable=('trac_wiki_blog.*', 'tractags.*', 'trac.*'))
        self.env.upgrade()
    
    def tearDown(self):
        self.env.destroy_temp_directory()
    
    # --------------------------------------------------------------------------
    # checking the /newblogpost page+template
    
    def _get_newblogpost(self):
        req = self.get_request('/newblogpost')
        response = self.simulate_request(req)
        assert_equals(200, response.code())
        return response
    
    def _get_newblogpost_dom(self):
        response = self._get_newblogpost()
        return BeautifulSoup(response.html())
    
    def test_has_page_to_create_a_new_blog_post(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        self._get_newblogpost()
    
    def test_has_correct_title(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        
        soup = self._get_newblogpost_dom()
        page_title = soup.find(name='title')
        assert_equals(u'Create New Blog Post \u2013 My Project', page_title.text.replace('\n', '').replace('\t', ''))
        
        wiki_content = soup.find(name='div', attrs={'id': 'content', 'class': 'wiki'})
        heading = wiki_content.find('h1')
        assert_equals('Create New Blog Post', heading.text)
    
    def test_has_only_one_field_for_blog_title(self):
        # This is a test case for the dreaded "item duplication" problem in
        # Genshi 0.5.1 (http://genshi.edgewall.org/ticket/254)
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        soup = self._get_newblogpost_dom()
        
        wiki_content = soup.find(name='div', attrs={'id': 'content', 'class': 'wiki'})
        title_fields = wiki_content.findAll(name='input', attrs={'name': 'blogtitle'})
        assert_length(1, title_fields)
    
    def test_sends_form_submission_to_the_same_url_as_the_initial_request(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        soup = self._get_newblogpost_dom()
        form = soup.find(name='form', attrs={'id': 'edit', 'method': 'post'})
        assert_equals('', form['action'])
        
    # TODO: Check: Tag interface
    # TODO: Check that the newblogpost page is only accessible for WIKI_MODIFY+TAGS_MODIFY
    # --------------------------------------------------------------------------
    # creating a new post
    
    def test_can_submit_a_new_blog_post(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        # TODO: Posting without version -> 500 in Trac
        req = self.post_request('/newblogpost', action='edit', save='Submit changes', blogtitle='title', text='some post', tags='blog', version=0)
        response = self.simulate_request(req)
        assert_equals(303, response.code())
        
        today = date.today()
        page = WikiPage(self.env, '%d/%02d/title' % (today.year, today.month))
        assert_true(page.exists)
        assert_equals('= title =\n\nsome post', page.text)
    
    # --------------------------------------------------------------------------
    # nav item
    
    def _newpost_link(self, path='/about'):
        # necessary so the /about path works. That's a good path because every 
        # user can access the page.
        import trac.about
        response = self.simulate_request(self.get_request(path))
        soup = BeautifulSoup(response.html())
        newpost_link = soup.find('a', attrs={'href': '/newblogpost'})
        return newpost_link
    
    def assert_newpost_link_is_displayed(self):
        newpost_link = self._newpost_link()
        assert_not_none(newpost_link)
        return newpost_link
    
    def assert_newpost_link_is_not_displayed(self):
        newpost_link = self._newpost_link()
        assert_none(newpost_link)
    
    def test_shows_link_to_new_blog_post_page_in_nav_bar(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        
        newpost_link = self.assert_newpost_link_is_displayed()
        assert_equals('New Blog Post', newpost_link.text)
    
    def test_shows_highlighted_link_when_on_the_newblogpost_page(self):
        self.grant_permission('anonymous', 'TRAC_ADMIN')
        # if there are any warnings because of a non-existing repository, Trac
        # will not highlight any navigation item
        self.disable_component(RepositoryManager)
        
        newpost_link = self._newpost_link('/newblogpost')
        nav_item = newpost_link.parent
        assert_equals('active', nav_item.get('class'))
    
    def test_only_show_newblogpost_link_if_user_has_enough_permissions(self):
        self.assert_has_permission('anonymous', 'WIKI_VIEW')
        
        self.grant_permission('anonymous', 'TAGS_MODIFY')
        self.assert_has_permission('anonymous', 'TAGS_MODIFY')
        self.assert_has_no_permission('anonymous', 'WIKI_CREATE')
        self.assert_newpost_link_is_not_displayed()

        self.revoke_permission('anonymous', 'TAGS_MODIFY')
        self.grant_permission('anonymous', 'WIKI_CREATE')
        self.assert_has_no_permission('anonymous', 'TAGS_MODIFY')
        self.assert_has_permission('anonymous', 'WIKI_CREATE')
        self.assert_newpost_link_is_not_displayed()

        self.grant_permission('anonymous', 'TAGS_MODIFY')
        self.assert_has_permission('anonymous', 'TAGS_MODIFY')
        self.assert_has_permission('anonymous', 'WIKI_CREATE')
        self.assert_newpost_link_is_displayed()