Exemplo n.º 1
0
    def test_change_persistence(self):
        SearchFrontend.query('Project.name_short == "PRJ"', self.user)

        # we now should have a non-persistent search
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 1)

        self.client.force_login(self.user)
        response = self.client.post(reverse('search:makepersistent'), {'pk': '1'})
        self.assertRedirects(response, reverse('search:advanced'))
        self.assertEqual(Search.objects.filter(creator=self.user, persistent=True).count(), 1)

        # try using already persistent object (should lead to 404)
        response = self.client.post(reverse('search:makepersistent'), {'pk': '1'})
        self.assertEqual(response.status_code, 404)

        # should also work for missing pks
        response = self.client.post(reverse('search:makepersistent'), {'pk': '2'}, follow=True)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Your account doesn't have access to this page.")

        # test deleting persistent items
        response = self.client.post(reverse('search:delpersistent'), {'pk': '1'})
        self.assertRedirects(response, reverse('search:advanced'))
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 0)

        # try deleting non-persistent item (should lead to 404)
        SearchFrontend.query('Project.name_short == "PRJ"', self.user)
        self.assertEqual(Search.objects.get(pk='2').persistent, False)
        response = self.client.post(reverse('search:delpersistent'), {'pk': '2'})
        self.assertEqual(response.status_code, 404)

        # try deleting non-present pk
        response = self.client.post(reverse('search:delpersistent'), {'pk': '3'}, follow=True)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Your account doesn't have access to this page.")
Exemplo n.º 2
0
 def test_fulltext_search(self):
     q = SearchFrontend.query('Issue', self.user)
     self.assertEqual(len(q), 4)
     q = SearchFrontend.query('iSSuE', self.user)
     self.assertEqual(len(q), 4)
     q = SearchFrontend.query('pro', self.user)
     self.assertEqual(len(q), 1)
     q = SearchFrontend.query('pRo', self.user)
     self.assertEqual(len(q), 1)
Exemplo n.º 3
0
    def test_search_for_tag(self):
        tag = Tag(tag_text='Test', project=self.project)
        tag.save()
        self.issue.tags.add(tag)

        result = SearchFrontend.query('test', self.user)
        self.assertEqual(len(result), 2)

        result = SearchFrontend.query('Issue.tags.tag_text ~~ "es"', self.user)
        self.assertEqual(len(result), 1)
Exemplo n.º 4
0
    def test_share_with_project_0(self):
        expression = 'User.username ~ "a"'
        SearchFrontend.query(expression, self.user)

        # we now should have a non-persistent search
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 1)

        self.client.force_login(self.user)
        response = self.client.post(reverse('search:makepersistent'), {'pk': '1'})
        self.assertRedirects(response, reverse('search:advanced'))
        self.assertEqual(Search.objects.filter(creator=self.user, persistent=True).count(), 1)

        search = Search.objects.first()
        search.shared_with.add(self.project)

        # we are creator of search, modifying should work
        description = 'new description'
        response = self.client.post(reverse('search:edit', kwargs={'sqn_sh': '1'}),
                                    {'description': description, 'searchexpression': expression},
                                    )
        self.assertRedirects(response, reverse('search:advanced'))

        search.refresh_from_db()
        self.assertEqual(search.description, description)

        # try with different creator, should not work
        search.creator = self.user2
        search.save()

        description = 'another description'
        response = self.client.post(reverse('search:edit', kwargs={'sqn_sh': '1'}),
                                    {'description': description, 'searchexpression': expression},
                                    follow=True,
                                    )
        self.assertContains(response, "Your account doesn't have access to this page.")

        search.refresh_from_db()
        self.assertNotEqual(search.description, description)

        # make user a manager for the project the search is shared with => should work
        search.shared_with.add(self.project)
        self.project.manager.add(self.user)

        description = 'even another description'
        response = self.client.post(reverse('search:edit', kwargs={'sqn_sh': '1'}),
                                    {'description': description, 'searchexpression': expression},
                                    follow=True,
                                    )
        self.assertRedirects(response, reverse('search:advanced'))

        search.refresh_from_db()
        self.assertEqual(search.description, description)
Exemplo n.º 5
0
    def post(self, request, *args, **kwargs):
        # result consists of a list of information about discovered objects:
        # [title, link]
        try:
            result = SearchFrontend.query(request.POST['expression'],
                                          self.request.user)
        except:
            # this can happen when less than three chars were given to fullext search
            messages.add_message(
                request, messages.ERROR,
                _('Please search for at least three characters'))
            result = []

        # prepare set of types contained in search result
        typeset = defaultdict(lambda: 0)
        for title, url, model in result:
            typeset[model] += 1

        # filter result list by object if necessary
        filterobj = ""
        if 'filterobj' in request.POST:
            filterobj = request.POST['filterobj']
            result = [x for x in result if x[2] == filterobj]

        return TemplateResponse(
            request, self.template_name, {
                'qresult': result,
                'typeset': sorted(typeset.items()),
                'qstring': request.POST['expression'],
                'filterobj': filterobj,
                'searchable_fields': searchable_fields,
                'compare': comp_expressions
            })
Exemplo n.º 6
0
    def test_constraints(self):
        comment = Comment(creator=self.user2,
                          issue=self.issuep2,
                          text="blub, sehr kreativ",
                          when=timezone.now())
        comment.save()
        comment = Comment(creator=self.user,
                          issue=self.issue,
                          text="blub",
                          when=timezone.now())
        comment.save()

        # contains expressions and the expected size of the resulting queryset
        tests = {
            'Project.name_short == "PRJ"': 0,
            'Project.issue.title ~~ "Issue"': 1,
            'Issue.type == "Bug"': 0,
            '(Issue.project.name_short ~~ "PR") OR (Issue.title ~~ "Bling")': 1,
            'Comment.text ~~ "blub"': 1,
            'Comment.text ~ "b.{2}b"': 1,
        }

        # use user2 for query this time (has only access to 2nd project)
        for t in tests:
            q = SearchFrontend.query(t, self.user2)
            self.assertEqual(len(q), tests[t])
            self.assertEqual(Search.objects.filter(creator=self.user2, searchexpression=t).count(), 1)
Exemplo n.º 7
0
    def test_share_with_project(self):
        expression = 'User.username ~ "a"'
        SearchFrontend.query(expression, self.user)

        # we now should have a non-persistent search
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 1)

        search = Search.objects.first()
        search.persistent = True
        search.shared_with.add(self.project)
        search.save()

        self.client.force_login(self.user2)
        response = self.client.post(reverse('project:search', kwargs={'project': 'PRJ'}), follow=True)
        self.assertContains(response, "Your account doesn't have access to this page.")

        self.assertEqual(Search.objects.filter(creator=self.user, persistent=True).count(), 1)
Exemplo n.º 8
0
    def post(self, request, *args, **kwargs):
        # result consists of a list of information about discovered objects:
        # [title, link]
        try:
            result = SearchFrontend.query(request.POST['expression'], self.request.user)
        except ValueError:
            # this can happen when less than three chars were given to full text search
            messages.add_message(request, messages.ERROR, _('Please search for at least three characters'))
            result = []

        # prepare set of types contained in search result
        # with/-out project filter
        typeset = defaultdict(lambda: [0, 0])
        # with/-out type filter
        projects = defaultdict(lambda: [0, 0])
        # with/-out type filter
        not_proj_related = defaultdict(lambda: [0, 0])
        for title, url, model, rel_project in result:
            typeset[model][1] += 1
            if FILTER_PROJ not in request.POST or rel_project == request.POST[FILTER_PROJ]:
                typeset[model][0] += 1
            # amount for this project with active type filter
            if _(NOT_PROJ_RELATED) == rel_project:
                not_proj_related[rel_project][1] += 1
                # amount for this project with active type filter
                if FILTER_TYPE not in request.POST or model == request.POST[FILTER_TYPE]:
                    not_proj_related[rel_project][0] += 1
            else:
                projects[rel_project][1] += 1
                # amount for this project with active type filter
                if FILTER_TYPE not in request.POST or model == request.POST[FILTER_TYPE]:
                    projects[rel_project][0] += 1

        # filter result list by object if necessary
        filtertype = ""
        if FILTER_TYPE in request.POST:
            filtertype = request.POST[FILTER_TYPE]
            result = [x for x in result if x[2] == filtertype]

        filterproj = ""
        if FILTER_PROJ in request.POST:
            filterproj = request.POST[FILTER_PROJ]
            result = [x for x in result if x[3] == filterproj]

        return TemplateResponse(request,
                                self.template_name,
                                {'qresult': result,
                                 'typeset': sorted(typeset.items()),
                                 # append the NOT_PROJ_RELATED entry always to the end
                                 'projects': sorted(projects.items())+list(not_proj_related.items()),
                                 'qstring': request.POST['expression'],
                                 FILTER_TYPE: filtertype,
                                 FILTER_PROJ: filterproj,
                                 'searchable_fields': searchable_fields,
                                 'compare': comp_expressions
                                 })
Exemplo n.º 9
0
    def test_search_for_tag(self):
        tag1 = Tag(tag_text='Test', project=Project.objects.get(name_short=p0_short))
        tag1.save()
        tag2 = Tag(tag_text='Test-Tag', project=Project.objects.get(name_short=p0_short))
        tag2.save()

        result = SearchFrontend.query('test', self.user)
        self.assertEqual(len(result), 2)

        result = SearchFrontend.query('Test-Tag', self.user)
        self.assertEqual(len(result), 1)

        # test fieldcheckings
        result = SearchFrontend.query('Tag.project.name_short ~~ "a"', self.user)
        self.assertEqual(len(result), 0)

        # test permission check
        user = get_user_model().objects.create_user('b', '*****@*****.**', 'b1234567')
        result = SearchFrontend.query('test', user)
        self.assertEqual(len(result), 0)
Exemplo n.º 10
0
    def test_share_with_project(self):
        expression = 'User.username ~ "a"'
        SearchFrontend.query(expression, self.user)

        # we now should have a non-persistent search
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 1)

        search = Search.objects.first()
        search.persistent = True
        search.shared_with.add(self.project)
        search.save()

        self.client.force_login(self.user2)
        user_doesnt_pass_test_and_gets_404(self,
                                           'project:search',
                                           address_kwargs={'project': 'PRJ'})

        self.assertEqual(
            Search.objects.filter(creator=self.user, persistent=True).count(),
            1)
Exemplo n.º 11
0
    def test_change_persistence(self):
        SearchFrontend.query('Project.name_short == "PRJ"', self.user)

        # we now should have a non-persistent search
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 1)

        self.client.force_login(self.user)
        response = self.client.post(reverse('search:makepersistent'),
                                    {'pk': '1'})
        self.assertRedirects(response, reverse('search:advanced'))
        self.assertEqual(
            Search.objects.filter(creator=self.user, persistent=True).count(),
            1)

        # try using already persistent object (should lead to 404)
        response = self.client.post(reverse('search:makepersistent'),
                                    {'pk': '1'})
        self.assertEqual(response.status_code, 404)

        # should also work for missing pks
        user_doesnt_pass_test_and_gets_404(self,
                                           'search:makepersistent',
                                           get_kwargs={'pk': '2'})

        # test deleting persistent items
        response = self.client.post(reverse('search:delpersistent'),
                                    {'pk': '1'})
        self.assertRedirects(response, reverse('search:advanced'))
        self.assertEqual(Search.objects.filter(creator=self.user).count(), 0)

        # try deleting non-persistent item (should lead to 404)
        SearchFrontend.query('Project.name_short == "PRJ"', self.user)
        self.assertEqual(Search.objects.get(pk='2').persistent, False)
        response = self.client.post(reverse('search:delpersistent'),
                                    {'pk': '2'})
        self.assertEqual(response.status_code, 404)

        # try deleting non-present pk
        user_doesnt_pass_test_and_gets_404(self,
                                           'search:delpersistent',
                                           get_kwargs={'pk': '3'})
Exemplo n.º 12
0
    def test_permissions(self):
        expression = '(User.username ~~ "a")'
        q = SearchFrontend.query(expression, self.user)

        self.assertEqual(Search.objects.count(), 1)

        search = Search.objects.first()

        self.assertEqual(str(search), expression)

        self.assertEqual(search.user_has_read_permissions(self.user), True)
        self.assertEqual(search.user_has_write_permissions(self.user), True)

        self.assertEqual(search.user_has_read_permissions(self.user2), False)
        self.assertEqual(search.user_has_write_permissions(self.user2), False)

        # set user2 as creator => user1 should not have read / write permissions
        search.creator = self.user2
        search.save()

        self.assertEqual(search.user_has_read_permissions(self.user), False)
        self.assertEqual(search.user_has_write_permissions(self.user), False)

        # share with project2 => user2 has read but not write permissions
        search.creator = self.user
        search.save()

        search.shared_with.add(self.project2)

        self.assertEqual(search.user_has_read_permissions(self.user2), True)
        self.assertEqual(search.user_has_write_permissions(self.user2), False)

        # share with project => user2 has no read and write permissions
        search.shared_with.clear()
        search.shared_with.add(self.project)

        self.assertEqual(search.user_has_read_permissions(self.user2), False)
        self.assertEqual(search.user_has_write_permissions(self.user2), False)
Exemplo n.º 13
0
    def test_clone_and_import(self):
        repo_path = '/tmp/gitpythonrepo'

        self.project.manager.add(self.user)
        self.project.developer.add(self.user2)
        self.project.save()

        filecontent1 = 'Hello World File 1'
        tmp1 = tempfile.NamedTemporaryFile(delete=False)
        tmp1.write(filecontent1.encode())
        tmp1.close()
        filecontent2 = 'Hello World File 2'
        tmp2 = tempfile.NamedTemporaryFile(delete=False)
        tmp2.write(filecontent2.encode())
        tmp2.close()

        with open(tmp1.name, 'r') as f1:
            with open(tmp2.name, 'r') as f2:
                response = self.client.post(reverse(
                    'project:gitintegration:create',
                    kwargs={'project': self.project.name_short}), {
                        'url': 'http://im-a-dum.my/repo/path',
                        'rsa_priv_path': f1,
                        'rsa_pub_path': f2,
                    },
                                            follow=True)
        self.assertNotContains(
            response, "Your account doesn't have access to this page")
        self.project.refresh_from_db()
        self.assertEqual(self.project.repos.count(), 1)
        repo = self.project.repos.first()
        self.assertEqual(repo.url, 'http://im-a-dum.my/repo/path')

        # set correct repo path. This is not possible via request due to validators
        repo.url = repo_path
        repo.save()

        self.assertEqual(repo.url, repo_path)
        self.assertIn(filecontent1, repo.rsa_priv_path.read().decode())
        self.assertIn(filecontent2, repo.rsa_pub_path.read().decode())
        # read() opened the file
        repo.rsa_priv_path.close()
        repo.rsa_pub_path.close()

        # try importing without valid remote repository
        shutil.rmtree(repo_path, ignore_errors=True)
        shutil.rmtree(repo.get_local_repo_path(), ignore_errors=True)
        import_commits()
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, False)

        # create a local repo
        initial_file = repo_path + '/initial'
        remote_repo = Repo.init(repo_path)
        f_open = open(initial_file, 'wb')
        f_open.write('Content in first file\n'.encode())
        f_open.close()
        remote_repo.index.add([initial_file])
        remote_repo_master = remote_repo.index.commit("initial commit")
        initial_sha = remote_repo_master.hexsha

        # try import again, connection should now work, but no commit to import
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(repo.last_commit_processed, remote_repo_master.hexsha)
        self.assertEqual(Commit.objects.count(), 0)

        # create commit with issue identifier in message
        f = repo_path + '/file1'
        open(f, 'wb').close()
        remote_repo.index.add([f])
        remote_repo_master = remote_repo.index.commit(self.project.name_short +
                                                      "-1 commit body")

        # import again, self.issue should now have a commit associated, activity shoud have increased
        activity = len(json.loads(repo.project.activity))
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertGreater(len(json.loads(repo.project.activity)), activity)
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(repo.last_commit_processed, remote_repo_master.hexsha)
        self.assertEqual(Commit.objects.count(), 1)
        self.assertEqual(self.issue.commits.count(), 1)

        # examine commit
        c = self.issue.commits.first()
        self.assertNotEqual(c.author, '')
        self.assertEqual(c.name, remote_repo_master.hexsha)
        self.assertEqual(c.repository, repo)
        self.assertEqual(c.message, "commit body")
        self.assertEqual(len(c.get_tags()), 0)
        firstchange = c.get_changes()['file1']
        self.assertEqual(firstchange['lines'], 0)
        self.assertEqual(firstchange['insertions'], 0)
        self.assertEqual(firstchange['deletions'], 0)

        # empty changes, get_changes() must not crash
        savedchanges = c.get_changes()
        c.changes = ""
        c.save()
        c.get_changes()
        c.set_changes(savedchanges)
        self.assertEqual(c.get_changes(), remote_repo_master.stats.files)

        # permissions checks maps to project's functions
        self.assertEqual(c.user_has_read_permissions(self.user), True)
        self.assertEqual(c.user_has_read_permissions(self.user2), True)
        self.assertEqual(c.user_has_write_permissions(self.user), True)
        self.assertEqual(c.user_has_write_permissions(self.user2), False)

        # reset last_commit_processed and try again: no duplicates should appear in Commits
        repo.last_commit_processed = ''
        repo.save()
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(repo.last_commit_processed, remote_repo_master.hexsha)
        self.assertEqual(Commit.objects.count(), 1)
        self.assertEqual(self.issue.commits.count(), 1)

        # commit with invalid issue id
        f = repo_path + '/file2'
        open(f, 'wb').close()
        remote_repo.index.add([f])
        remote_repo_master = remote_repo.index.commit(
            self.project.name_short + "-42 commit body with invalid issue id")
        # activity should not change
        activity = len(json.loads(repo.project.activity))
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertEqual(len(json.loads(repo.project.activity)), activity)
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(repo.last_commit_processed, remote_repo_master.hexsha)
        self.assertEqual(Commit.objects.count(), 1)
        self.assertEqual(self.issue.commits.count(), 1)

        # create commit with issue identifier in message
        f = repo_path + '/file3'
        f_open = open(f, 'wb')
        f_open.write('Fancy file content\nEven with newline\n'.encode())
        f_open.close()
        remote_repo.index.add([f])
        remote_repo_master = remote_repo.index.commit(
            self.project.name_short + "-1 commit body for file 3\n" +
            "This time with longer commit message")
        tag = remote_repo.create_tag('Test-Tag', ref=remote_repo_master)

        # import again, self.issue should now have 2 commits associated
        activity = len(json.loads(repo.project.activity))
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertGreater(len(json.loads(repo.project.activity)), activity)
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(repo.last_commit_processed, remote_repo_master.hexsha)
        self.assertEqual(Commit.objects.count(), 2)
        self.assertEqual(self.issue.commits.count(), 2)

        # examine newest commit
        c = self.issue.commits.get(name=remote_repo_master.hexsha)
        self.assertNotEqual(c.author, '')
        self.assertEqual(c.name, remote_repo_master.hexsha)
        self.assertEqual(c.repository, repo)
        self.assertEqual(
            c.message,
            "commit body for file 3\nThis time with longer commit message")
        self.assertEqual(c.get_title(), "commit body for file 3")
        self.assertEqual(c.get_name_short(), remote_repo_master.hexsha[:7])
        firstchange = c.get_changes()['file3']
        self.assertEqual(firstchange['lines'], 2)
        self.assertEqual(firstchange['insertions'], 2)
        self.assertEqual(firstchange['deletions'], 0)
        self.assertEqual(c.__str__(), "Commit " + remote_repo_master.hexsha)
        self.assertEqual(len(c.get_tags()), 1)
        self.assertEqual(c.get_tags()[0], 'Test-Tag')

        # test file diff view
        diff = '@@ -0,0 +1,2 @@\n+Fancy file content\n+Even with newline\n'.splitlines(
        )
        response = self.client.post(
            reverse('issue:commit_diff',
                    kwargs={
                        'project': self.project.name_short,
                        'sqn_i': c.issue.number,
                    }),
            {
                'filename': list(c.get_changes().keys())[0],
                'repository': repo.pk,
                'commit_sha': c.get_name_short(),
            },
        )
        self.assertNotContains(
            response, "Your account doesn't have access to this page")
        self.assertEqual(response.context_data['diff'], diff)
        self.assertEqual(response.context_data['filename'],
                         list(c.get_changes().keys())[0])
        self.assertEqual(response.context_data['commit_sha'],
                         c.get_name_short())

        # add another tag to an already imported commit
        tag = remote_repo.create_tag('Another_tag', ref=remote_repo_master)
        activity = len(json.loads(repo.project.activity))
        Frontend.import_new_commits(repo)
        repo.refresh_from_db()
        self.assertGreater(len(json.loads(repo.project.activity)), activity)

        c = self.issue.commits.get(name=remote_repo_master.hexsha)
        self.assertEqual(len(c.get_tags()), 2)
        self.assertIn('Test-Tag', c.get_tags())
        self.assertIn('Another_tag', c.get_tags())

        # check with insufficient privileges
        self.project.manager.clear()
        user_doesnt_pass_test_and_gets_404(
            self,
            'issue:commit_diff',
            address_kwargs={
                'project': self.project.name_short,
                'sqn_i': c.issue.number,
            },
            get_kwargs={
                'filename': list(c.get_changes().keys())[0],
                'repository': repo.pk,
                'commit_sha': c.get_name_short(),
            },
        )
        self.project.manager.add(self.user)

        # post broken data to view
        response = self.client.post(reverse('issue:commit_diff',
                                            kwargs={
                                                'project':
                                                self.project.name_short,
                                                'sqn_i': c.issue.number,
                                            }), {
                                                'filename': 'blabla',
                                                'repository': repo.pk,
                                                'commit_sha': 'blubber',
                                            },
                                    follow=True)
        self.assertEqual(response.context_data['diff'], ''.splitlines())
        self.assertEqual(response.context_data['filename'], 'blabla')
        self.assertEqual(response.context_data['commit_sha'], 'blubber')

        # check that commits are searchable
        sr = SearchFrontend.query('commit body', self.user)
        self.assertEqual(len(sr), 2)
        sr = SearchFrontend.query('Commit.message ~ "commit message"',
                                  self.user)
        self.assertEqual(len(sr), 1)
        self.assertEqual(sr[0][0],
                         "(" + c.get_name_short() + ") commit body for file 3")

        # examine file diffs
        f = repo_path + '/file4'
        f_open = open(f, 'wb')
        f_open.write('Fancy file content\n'.encode())
        f_open.close()
        remote_repo.index.add([f])
        remote_repo_master = remote_repo.index.commit('file4')
        Frontend.import_new_commits(repo)

        diff = Frontend.get_diff(repo, remote_repo_master.hexsha, 'file4')
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(diff, "@@ -0,0 +1 @@\n+Fancy file content\n")

        # check that commit changes are searchable
        sr = SearchFrontend.query('file', self.user)
        self.assertEqual(len(sr), 1)

        # check with first commit
        diff = Frontend.get_diff(repo, initial_sha, 'initial')
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        # TODO TESTCASE we're currently expecting an empty result because gitpython is broken as f**k
        self.assertEqual(diff, "")
        # self.assertEqual(diff, "@@ -0,0 +1 @@\n+Content in first file\n")

        # try with invalid filename
        diff = Frontend.get_diff(repo, c.get_name_short(), 'invalid')
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(diff, "")

        # try with invalid commit sha
        diff = Frontend.get_diff(repo, '1234567', 'invalid')
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, True)
        self.assertEqual(diff, "")

        # try with broken repo path (not yet checked out
        prj_name_short = self.project.name_short
        self.project.name_short = 'AAA'
        self.project.save()
        diff = Frontend.get_diff(repo, initial_sha, 'initial')
        repo.refresh_from_db()
        self.assertEqual(repo.conn_ok, False)
        self.assertEqual(diff, "")
        self.project.name_short = prj_name_short
        self.project.save()

        # delete the key files from the server
        os.unlink(repo.rsa_priv_path.path)
        os.unlink(repo.rsa_pub_path.path)
        # delete the key files locally
        os.unlink(tmp1.name)
        os.unlink(tmp2.name)
        # clean up locally
        shutil.rmtree(repo_path, ignore_errors=True)
        shutil.rmtree(repo.get_local_repo_path(), ignore_errors=True)
Exemplo n.º 14
0
    def test_new_search(self):
        driver = self.selenium
        driver.get('{}{}'.format(self.live_server_url,
                                 reverse('landing_page:home')))

        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(
            By.NAME, "expression").send_keys("Project.name_short ~~ \"PRJ\"")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()
        self.assertEqual(
            self.project.name,
            driver.find_element(
                By.CSS_SELECTOR,
                ".list-group > li:nth-child(2) > h4:nth-child(1) > a:nth-child(1)"
            ).text)
        self.assertEqual(
            self.project2.name,
            driver.find_element(
                By.CSS_SELECTOR,
                ".list-group > li:nth-child(1) > h4:nth-child(1) > a:nth-child(1)"
            ).text)
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        self.assertIn("Project.name_short ~~ "PRJ"",
                      driver.page_source)
        driver.find_element(By.CSS_SELECTOR,
                            "#search1 > button.btn.btn-default").click()
        self.assertEqual(
            self.project.name,
            driver.find_element(
                By.CSS_SELECTOR,
                ".list-group > li:nth-child(2) > h4:nth-child(1) > a:nth-child(1)"
            ).text)
        self.assertEqual(
            self.project2.name,
            driver.find_element(
                By.CSS_SELECTOR,
                ".list-group > li:nth-child(1) > h4:nth-child(1) > a:nth-child(1)"
            ).text)
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(
            By.NAME,
            "expression").send_keys("Issue.title ~~ \"Issue for Proj1\"")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()
        self.assertEqual(
            "(PRJ-2) Another Issue for Proj1",
            driver.find_element(
                By.CSS_SELECTOR,
                ".list-group > li:nth-child(2) > h4:nth-child(1) > a:nth-child(1)"
            ).text)
        driver.find_element(By.CSS_SELECTOR, "a.dropdown-toggle").click()
        self.assertIn("Issue.title ~~ "Issue for Proj1"",
                      driver.page_source)
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(
            By.NAME,
            "expression").send_keys("User.username == \"michgibtsnicht\"")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()
        self.assertEqual("No items matching your query found",
                         driver.find_element(By.CSS_SELECTOR, ".alert").text)
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(
            By.NAME, "expression").send_keys("Comment.invalidfield ~~ \"b\"")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()
        self.assertEqual("No items matching your query found",
                         driver.find_element(By.CSS_SELECTOR, ".alert").text)
        driver.find_element(By.CSS_SELECTOR,
                            "span.glyphicon.glyphicon-search").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(By.NAME, "expression").send_keys("()aaa")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()
        self.assertEqual("No items matching your query found",
                         driver.find_element(By.CSS_SELECTOR, ".alert").text)

        # full-text search
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(By.NAME, "expression").send_keys("iss")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()

        self.assertIn(
            "Issue",
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_Issue > button:nth-child(4)").text)
        self.assertIn(
            "Project",
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_Project > button:nth-child(4)").text)
        self.assertIn(
            "User",
            driver.find_element(By.CSS_SELECTOR,
                                "#filtertype_User > button:nth-child(4)").text)

        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-9 ul").text.split('\n')), 10)

        driver.find_element(By.CSS_SELECTOR,
                            "#filtertype_Issue > button:nth-child(4)").click()

        # check that Issue button is now active
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "button.list-group-item:nth-child(3)").get_attribute('class'),
            'list-group-item active')

        # check result list lengths for all buttons
        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-9 ul").text.split('\n')), 3)

        driver.find_element(
            By.CSS_SELECTOR,
            "#filtertype_Project > button:nth-child(4)").click()
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "button.list-group-item:nth-child(3)").get_attribute('class'),
            'list-group-item active')
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_Issue > button:nth-child(4)").get_attribute(
                    'class'), 'list-group-item')

        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-9 ul").text.split('\n')), 1)

        driver.find_element(By.CSS_SELECTOR,
                            "#filtertype_User > button:nth-child(4)").click()
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "button.list-group-item:nth-child(3)").get_attribute('class'),
            'list-group-item active')
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_Project > button:nth-child(4)").get_attribute(
                    'class'), 'list-group-item')
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_Issue > button:nth-child(4)").get_attribute(
                    'class'), 'list-group-item')

        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-9 ul").text.split('\n')), 1)

        # disable currently selected button and check result list size and highlighting
        driver.find_element(By.CSS_SELECTOR,
                            "button.list-group-item:nth-child(3)").click()
        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-9 ul").text.split('\n')), 10)
        self.assertEqual(
            driver.find_element(
                By.CSS_SELECTOR,
                "#filtertype_User > button:nth-child(4)").get_attribute(
                    'class'), 'list-group-item')

        # test empty search string (should fail)
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(By.NAME, "expression").send_keys("")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()

        self.assertIn('Please search for at least three characters',
                      driver.page_source)

        # should always fail with less than three chars
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.NAME, "expression").clear()
        driver.find_element(By.NAME, "expression").send_keys("aa")
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-default").click()

        self.assertIn('Please search for at least three characters',
                      driver.page_source)

        # test marking search persistent
        qstring = 'Issue.type == "Bug"'
        q = SearchFrontend.query(qstring, self.user)
        self.assertEqual(len(q), 2)
        driver.find_element(By.CSS_SELECTOR, "span.caret").click()
        driver.find_element(By.ID, "recent-searches-link").click()
        driver.find_element(By.CSS_SELECTOR, "button.btn.btn-link").click()
        driver.find_element(
            By.CSS_SELECTOR,
            "div.col-md-6:nth-child(2) > div:nth-child(1) > table:nth-child(2) >"
            +
            " tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2) > a:nth-child(1)"
        ).click()
        self.assertEqual(
            driver.find_element(By.ID,
                                "id_searchexpression").get_attribute("value"),
            qstring)
        driver.find_element(By.ID, "id_description").clear()
        driver.find_element(By.ID, "id_description").send_keys("Fancy filter")
        self.assertEqual(
            Search.objects.get(searchexpression=qstring).persistent, True)

        driver.find_element(By.CSS_SELECTOR,
                            ".select2-selection__rendered").click()
        time.sleep(1)
        for i in driver.find_elements(By.CSS_SELECTOR,
                                      '#select2-id_shared_with-results li'):
            if i.text == self.project.name:
                i.click()
                break
        driver.find_element(By.CSS_SELECTOR, ".save").click()
        driver.find_element(By.LINK_TEXT, "Projects").click()
        driver.find_element(By.LINK_TEXT, self.project.name).click()
        driver.find_element(By.LINK_TEXT, "Settings").click()
        driver.find_element(By.LINK_TEXT, "Search filters").click()
        elem = driver.find_element(By.CSS_SELECTOR, ".btn-link")
        self.assertEqual(elem.text, "Fancy filter")
        elem.click()
        self.assertEqual(
            len(
                driver.find_element(By.CSS_SELECTOR,
                                    ".col-md-12 ul").text.split("\n")), 3)

        # test delete
        driver.get('{}{}'.format(self.live_server_url,
                                 reverse('search:advanced')))
        driver.find_element(
            By.CSS_SELECTOR,
            "div.col-md-6:nth-child(2) > div:nth-child(1) > " +
            "table:nth-child(2) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(3) > "
            + "form:nth-child(1) > button:nth-child(3)").click()
        self.assertEqual(len(Search.objects.filter(searchexpression=qstring)),
                         0)
Exemplo n.º 15
0
    def test_parser(self):
        user = self.user
        project = self.project
        project2 = self.project2

        # contains expressions and the expected size of the resulting queryset
        tests = {
            'Project.name_short == "PRJ"': 1,
            'Project.issue.title ~~ "Issue"': 2,
            'Issue.type == "Bug"': 2,
            'Issue.type != "Bug"': 2,
            'Issue.number >= 2': 2,
            'Issue.number >= 2 LIMIT 1': 1,
            'Issue.number >= 2 SORT ASC Issue.number LIMIT 2': 2,
            'Issue.number >= 2 LIMIT 2 SORT ASC Issue.number': 2,
            'Issue.due_date <= 20051005': 1,
            '(Project.name_short ~~ "PRJ") AND (Project.issue.title == "Blub-Issue")': 1,
            '(Issue.project.name_short ~~ "PRJ") AND (Issue.title ~~ "Issue")': 3,
            '(Issue.project.name_short ~~ "PR") AND (Issue.title ~~ "Issue")': 4,
            '(Issue.project.name_short ~~ "PR") OR (Issue.title ~~ "Bling")': 4,
            '(Issue.project.name_short ~~ "PR") OR (Issue.title ~~ "Bling") SORT ASC Issue__number': 4,
            '(Issue.project.name_short ~~ "PR") OR (Issue.title ~~ "Bling") SORT DESC Issue__number': 4,
            '(Issue.project.name_short ~~ "PR") OR (Issue.title ~~ "Bling") LIMIT 3': 3,
            'Comment.text == "blub"': 0,
            '(User.username ~~ "a")': 1,
        }

        for t in tests:
            q = SearchFrontend.query(t, user)
            self.assertEqual(len(q), tests[t])
            self.assertEqual(Search.objects.filter(creator=user, searchexpression=t).count(), 1)

        # check minlength checking
        self.assertRaises(ValueError, SearchFrontend.query, 'aa', user)
        # minlength checking must also work when combining
        # short expressions by AND or OR with valid expressions
        self.assertRaises(ValueError, SearchFrontend.query, 'Bla AND   OR Blub', user)
        self.assertRaises(ValueError, SearchFrontend.query, 'Bla OR   OR Blub', user)
        self.assertRaises(ValueError, SearchFrontend.query, 'Bla OR   AND Blub', user)

        # check duplicate checking
        expression = 'Issue.type == "Bug"'
        q = SearchFrontend.query(expression, user)
        self.assertEqual(len(q), 2)
        self.assertEqual(Search.objects.filter(creator=user, searchexpression=expression).count(), 1)

        # assert that non-persistent searches are removed from model
        self.assertEqual(Search.objects.filter(creator=user, persistent=False).count(), 10)

        # expressions that shall not be stored in the database
        tests = {
            # fulltext searches
            'iss': 4,
            'Blu AND iss': 1,
            'Blu AND iss OR Bla AND iss OR Bli AND iss': 3,
            'Bli AND lin AND sue': 1,
            'Bling OR Bla': 2,
            'Bli OR Iss AND Bla': 2,
            # broken regexes
            'Comment.text ~ "?{42}.': 0,
        }

        for t in tests:
            q = SearchFrontend.query(t, user)
            self.assertEqual(len(q), tests[t])
            self.assertEqual(Search.objects.filter(creator=user, searchexpression=t).count(), 0)

        # negative tests
        tests = [
            'Project.name_short == "PRJ" AND OR Project.namme ~~ "T"',
            'Issue.due_date >= 20121340',
            'Issue.due_date >= 20100101 SORT Issue.number',
            'Issue.due_date >= 20100101 SORT ASC',
            'Issue.due_date >= 20100101 LIMIT',
            'Project.name <> "PRJ"',
            'Project.name <= PRJ',
            'Project.name',
            'LIMIT 3',
            'Project.invalidfield ~~ "blubber"',
            'Invalidobject.field ~~ "blubber"',
        ]

        for t in tests:
            self.assertRaises(Exception, parser.compile, t)

        # set searchable_fields to invalid values and check behavior
        Project.searchable_fields.append('invalidfield')
        self.assertRaises(Exception, parser.compile, 'Project.invalidfield ~~ "blubber"')
        Project.searchable_fields = []
        q = SearchFrontend.query('blubber', user)
        self.assertEqual(len(q), 0)

        # assert that non-persistent searches are removed from model
        self.assertEqual(Search.objects.filter(creator=user, persistent=False).count(), 10)
Exemplo n.º 16
0
    def test_search_for_tag(self):
        result = SearchFrontend.query('test', self.user)
        self.assertEqual(len(result), 2)

        result = SearchFrontend.query('Issue.tags.tag_text ~~ "es"', self.user)
        self.assertEqual(len(result), 1)