#2408 Star a project
Merged 6 years ago by pingou. Opened 6 years ago by vivekanand1101.
vivekanand1101/pagure start  into  master

@@ -0,0 +1,51 @@ 

+ """star_a_project

+ 

+ Revision ID: c34f4b09ef18

+ Revises: 8a5d68f74beb

+ Create Date: 2017-07-07 00:08:18.257075

+ 

+ """

+ 

+ # revision identifiers, used by Alembic.

+ revision = 'c34f4b09ef18'

+ down_revision = '8a5d68f74beb'

+ 

+ from alembic import op

+ import sqlalchemy as sa

+ 

+ 

+ def upgrade():

+     ''' Add a new table to store data about who starred which project '''

+     op.create_table(

+         'stargazers',

+         sa.Column('id', sa.Integer, primary_key=True),

+         sa.Column(

+             'project_id',

+             sa.Integer,

+             sa.ForeignKey(

+                 'projects.id', onupdate='CASCADE', ondelete='CASCADE'),

+             nullable=False,

+             index=True,

+         ),

+         sa.Column(

+             'user_id',

+             sa.Integer,

+             sa.ForeignKey('users.id', onupdate='CASCADE', ondelete='CASCADE'),

+             nullable=False,

+         )

+     )

+ 

+     op.create_unique_constraint(

+         constraint_name='uq_stargazers_project_id_user_id_key',

+         table_name='stargazers',

+         columns=['project_id', 'user_id']

+     )

+ 

+ 

+ def downgrade():

+     ''' Remove the stargazers table from the database '''

+     op.drop_constraint(

+         constraint_name='uq_stargazers_project_id_user_id_key',

+         table_name='stargazers'

+     )

+     op.drop_table('stargazers')

file modified
+3
@@ -500,6 +500,9 @@ 

              flask.g.repo_forked = pagure.get_authorized_project(

                  SESSION, repo, user=flask.g.fas_user.username,

                  namespace=namespace)

+             flask.g.repo_starred = pagure.lib.has_starred(

+                 SESSION, flask.g.repo, user=flask.g.fas_user.username,

+             )

  

          if not flask.g.repo \

                  and APP.config.get('OLD_VIEW_COMMIT_ENABLED', False) \

file modified
+109
@@ -4359,3 +4359,112 @@ 

          'first': first_page,

          'last': last_page

      }

+ 

+ 

+ def update_star_project(session, repo, star, user):

+     ''' Unset or set the star status depending on the star value.

+ 

+     :arg session: the session to use to connect to the database.

+     :arg repo: a model.Project object representing the project to star/unstar

+     :arg star: '1' for starring and '0' for unstarring

+     :arg user: string representing the user

+     :return: None or string containing 'You starred this project' or

+             'You unstarred this project'

+     '''

+ 

+     if not all([repo, user, star]):

+         return

+     user_obj = get_user(session, user)

+     msg = None

+     if star == '1':

+         msg = _star_project(

+             session,

+             repo=repo,

+             user=user_obj,

+         )

+     elif star == '0':

+         msg = _unstar_project(

+             session,

+             repo=repo,

+             user=user_obj,

+         )

+     return msg

+ 

+ 

+ def _star_project(session, repo, user):

+     ''' Star a project

+ 

+     :arg session: Session object to connect to db with

+     :arg repo: model.Project object representing the repo to star

+     :arg user: model.User object who is starring this repo

+     :return: None or string containing 'You starred this project'

+     '''

+ 

+     if not all([repo, user]):

+         return

+     stargazer_obj = model.Star(

+         project_id=repo.id,

+         user_id=user.id,

+     )

+     session.add(stargazer_obj)

+     return 'You starred this project'

+ 

+ 

+ def _unstar_project(session, repo, user):

+     ''' Unstar a project

+     :arg session: Session object to connect to db with

+     :arg repo: model.Project object representing the repo to unstar

+     :arg user: model.User object who is unstarring this repo

+     :return: None or string containing 'You unstarred this project'

+             or 'You never starred the project'

+     '''

+ 

+     if not all([repo, user]):

+         return

+     # First find the stargazer_obj object

+     stargazer_obj = _get_stargazer_obj(session, repo, user)

+     if isinstance(stargazer_obj, model.Star):

+         session.delete(stargazer_obj)

+         msg = 'You unstarred this project'

+     else:

+         msg = 'You never starred the project'

+     return msg

+ 

+ 

+ def _get_stargazer_obj(session, repo, user):

+     ''' Query the db to find stargazer object with given repo and user

+     :arg session: Session object to connect to db with

+     :arg repo: model.Project object

+     :arg user: model.User object

+     :return: None or model.Star object

+     '''

+ 

+     if not all([repo, user]):

+         return

+     stargazer_obj = session.query(

+         model.Star,

+     ).filter(

+         model.Star.project_id == repo.id,

+     ).filter(

+         model.Star.user_id == user.id,

+     )

+ 

+     return stargazer_obj.first()

+ 

+ 

+ def has_starred(session, repo, user):

+     ''' Check if a given user has starred a particular project

+ 

+     :arg session: The session object to query the db with

+     :arg repo: model.Project object for which the star is checked

+     :arg user: The username of the user in question

+     :return: True if user has starred the project, False otherwise

+     '''

+ 

+     if not all([repo, user]):

+         return

+     user_obj = search_user(session, username=user)

+     stargazer_obj = _get_stargazer_obj(session, repo, user_obj)

+     if isinstance(stargazer_obj, model.Star):

+         return True

+     return False

file modified
+41
@@ -2097,6 +2097,47 @@ 

      __table_args__ = (sa.UniqueConstraint('project_id', 'group_id'),)

  

  

+ class Star(BASE):

+     """ Stores users association with the all the projects which

+     they have starred

+ 

+     Table -- star

+     """

+ 

+     __tablename__ = 'stargazers'

+     __table_args__ = (

+         sa.UniqueConstraint(

+             'project_id',

+             'user_id',

+             name='uq_stargazers_project_id_user_id_key'),

+     )

+ 

+     id = sa.Column(sa.Integer, primary_key=True)

+     project_id = sa.Column(

+         sa.Integer,

+         sa.ForeignKey('projects.id', onupdate='CASCADE', ondelete='CASCADE'),

+         nullable=False,

+         index=True,

+     )

+     user_id = sa.Column(

+         sa.Integer,

+         sa.ForeignKey('users.id', onupdate='CASCADE', ondelete='CASCADE'),

+         nullable=False,

+     )

+     user = relation(

+         'User', foreign_keys=[user_id], remote_side=[User.id],

+         backref=backref(

+             'stars', cascade="delete, delete-orphan"

+         ),

+     )

+     project = relation(

+         'Project', foreign_keys=[project_id], remote_side=[Project.id],

+         backref=backref(

+             'stargazers', cascade="delete, delete-orphan",

+         ),

+     )

+ 

+ 

  class Watcher(BASE):

      """ Stores the user of a projects.

  

@@ -75,6 +75,11 @@ 

                      url_for('view_user_requests', username=g.fas_user.username)

                      }}">My Pull Requests</a>

                    <div class="dropdown-divider"></div>

+                   <a class="dropdown-item" href="{{

+                     url_for('view_user_stars', username=g.fas_user.username)

+                     }}">My Stars</a>

+                   <div class="dropdown-divider"></div>

+ 

                    <a class="dropdown-item" href="{{ url_for('auth_logout')

                      }}?next={{request.url}}">Log Out</a>

                  </div>

@@ -50,6 +50,48 @@ 

              class="btn btn-success btn-sm">New Issue</a>

            {% endif %}

            <div class="btn-group">

+           {% if not g.repo_starred %}

+             <form method="POST" name="star_project" id="star_project"

+               action="{{ url_for(

+               '.star_project',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               star=1)}}">

+               {{ forkbuttonform.csrf_token }}

+             </form>

+               <button class="btn btn-sm btn-secondary"

+               onclick="$('#star_project').submit();">

+                 <span class="oi" data-glyph="star"></span>Star</button>

+                 <a href="{{url_for(

+                             'view_stargazers',

+                             repo=repo.name,

+                             username=repo.user.user if repo.is_fork else None,

+                             namespace=repo.namespace,

+                 )}}" class="btn btn-sm btn-primary">{{repo.stargazers|length}}</a>

+           {% else %}

+             <form method="POST" name="unstar_project" id="unstar_project"

+               action="{{ url_for(

+               '.star_project',

+               repo=repo.name,

+               username=username,

+               namespace=repo.namespace,

+               star=0)}}">

+               {{ forkbuttonform.csrf_token }}

+             </form>

+               <button class="btn btn-sm btn-secondary"

+               onclick="$('#unstar_project').submit();">

+                 <span class="oi" data-glyph="star"></span>Unstar</button>

+                 <a href="{{url_for(

+                             'view_stargazers',

+                             repo=repo.name,

+                             username=repo.user.user if repo.is_fork else None,

+                             namespace=repo.namespace,

+                 )}}" class="btn btn-sm btn-primary">{{repo.stargazers|length}}</a>

+           {% endif %}

+ 	</div>

+ 

+ 	<div class="btn-group">

            {% if not repo.is_fork %}

              {% if g.repo_forked %}

                <a href="{{ url_for(

@@ -0,0 +1,36 @@ 

+ {% extends "repo_master.html" %}

+ 

+ {% block title %}Stargazers of {{ repo.fullname }} {% endblock %}

+ 

+ {% block content %}

+ <div class="p-t-2">

+   <div class="container">

+     <h3 class="p-b-2">

+       Starred by {{ users | length}} users

+     </h3>

+     <hr>

+       <table class="table table-hover table-striped m-b-0 m-t-1">

+         <thead class="thead-default">

+           <tr>

+             <th class="nowrap">Stargazers of {{ repo.fullname }} </th>

+           </tr>

+         </thead>

+         <tbody>

+           {% for user in users %}

+             <tr class="nowrap">

+               <td>

+                 <img src="{{ user.default_email | avatar_url(36) | safe }}" width=20 height=20 />

+               <a href="{{ url_for(

+                 'view_user',

+                 username=user.user,

+               )}}">{{user.user}}

+               </a></br>

+               </td>

+             </tr>

+           {% endfor %}

+         </tbody>

+       </table>

+       <br>

+   </div>

+ </div>

+ {% endblock %}

@@ -0,0 +1,51 @@ 

+ {% extends "master.html" %}

+ 

+ {% block title %}{{ username }}'s starred Projects{% endblock %}

+ 

+ {% block content %}

+ <div class="p-t-2">

+   <div class="container">

+     <h3 class="p-b-2">

+       {{ repos | length }} Projects Starred by {{ username }}

+     </h3>

+     <hr>

+       <table class="table table-hover table-striped m-b-0 m-t-1">

+         <thead class="thead-default">

+           <tr>

+             <th class="nowrap">Starred Projects</th>

+           </tr>

+         </thead>

+         <tbody>

+           {% for repo in repos %}

+             <tr class="nowrap">

+               <td>

+                 {% if repo.avatar_email %}

+                 <img src="{{ repo.avatar_email | avatar_url | safe }}" width=20 height=20 />

+                 <a href="{{ url_for(

+                 'view_repo',

+                 repo=repo.name,

+                 username=repo.user.user if repo.is_fork else None,

+                 namespace=repo.namespace,

+                 )}}">{{repo.fullname}}</a>

+                 </br>

+                 {% else %}

+                <div class="col-sm-12">

+                  <span class="oi" data-glyph="document"></span>

+                 <a href="{{ url_for(

+                 'view_repo',

+                 repo=repo.name,

+                 username=repo.user.user if repo.is_fork else None,

+                 namespace=repo.namespace,

+                 )}}">{{repo.fullname}}</a>

+                 </div>

+                 </br>

+                 {% endif %}

+               </td>

+             </tr>

+           {% endfor %}

+         </tbody>

+       </table>

+       <br>

+   </div>

+ </div>

+ {% endblock %}

file modified
+19
@@ -432,6 +432,25 @@ 

      )

  

  

+ @APP.route('/user/<username>/stars/')

+ @APP.route('/user/<username>/stars')

+ def view_user_stars(username):

+     """

+     Shows the starred projects of the specified user.

+ 

+     :arg username: The username whose stars we have to retrieve

+     """

+ 

+     user = _get_user(username=username)

+ 

+     return flask.render_template(

+         'user_stars.html',

+         username=username,

+         user=user,

+         repos=[star.project for star in user.stars],

+     )

+ 

+ 

  @APP.route('/new/', methods=('GET', 'POST'))

  @APP.route('/new', methods=('GET', 'POST'))

  @login_required

file modified
+57
@@ -2263,6 +2263,63 @@ 

      )

  

  

+ @APP.route('/<repo>/stargazers/')

+ @APP.route('/fork/<username>/<repo>/stargazers/')

+ @APP.route('/<namespace>/<repo>/stargazers/')

+ @APP.route('/fork/<username>/<namespace>/<repo>/stargazers/')

+ def view_stargazers(repo, username=None, namespace=None):

+     ''' View all the users who have starred the project '''

+ 

+     stargazers = flask.g.repo.stargazers

+     users = [star.user for star in stargazers]

+     return flask.render_template(

+         'repo_stargazers.html', repo=flask.g.repo, users=users)

+ 

+ 

+ @APP.route('/<repo>/star/<star>', methods=["POST"])

+ @APP.route('/fork/<username>/<repo>/star/<star>', methods=["POST"])

+ @APP.route('/<namespace>/<repo>/star/<star>', methods=["POST"])

+ @APP.route('/fork/<username>/<namespace>/<repo>/star/<star>', methods=["POST"])

+ @login_required

+ def star_project(repo, star, username=None, namespace=None):

+     ''' Star or Unstar a project

+ 

+     :arg repo: string representing the project which has to be starred or

+     unstarred.

+     :arg star: either '0' or '1' for unstar and star respectively

+     :arg username: string representing the user the fork of whose is being

+     starred or unstarred.

+     :arg namespace: namespace of the project if any

+     '''

+ 

+     return_point = flask.url_for('index')

+     if (

+             flask.request.referrer is not None and

+             pagure.is_safe_url(flask.request.referrer)):

+         return_point = flask.request.referrer

+ 

+     form = pagure.forms.ConfirmationForm()

+     if not form.validate_on_submit():

+         flask.abort(400)

+ 

+     if star not in ['0', '1']:

+         flask.abort(400)

+ 

+     try:

+         msg = pagure.lib.update_star_project(

+             SESSION,

+             user=flask.g.fas_user.username,

+             repo=flask.g.repo,

+             star=star,

+         )

+         SESSION.commit()

+         flask.flash(msg)

+     except SQLAlchemyError:

+         flask.flash('Could not star the project')

+ 

+     return flask.redirect(return_point)

+ 

+ 

  @APP.route('/<repo>/watch/settings/<watch>', methods=['POST'])

  @APP.route('/<namespace>/<repo>/watch/settings/<watch>', methods=['POST'])

  @APP.route(

@@ -0,0 +1,269 @@ 

+ # coding=utf-8

+ 

+ """

+  (c) 2017 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+    Vivek Anand <vivekanand1101@gmail.com>

+ 

+ """

+ 

+ __requires__ = ['SQLAlchemy >= 0.8']

+ import pkg_resources

+ 

+ import unittest

+ import sys

+ import os

+ 

+ sys.path.insert(0, os.path.join(os.path.dirname(

+     os.path.abspath(__file__)), '..'))

+ 

+ import pagure

+ import pagure.lib

+ import tests

+ 

+ 

+ class TestStarProjectUI(tests.SimplePagureTest):

+     def setUp(self):

+         """ Set up the environnment, ran before every tests. """

+         super(TestStarProjectUI, self).setUp()

+ 

+         pagure.APP.config['TESTING'] = True

+         pagure.SESSION = self.session

+         pagure.ui.SESSION = self.session

+         pagure.ui.app.SESSION = self.session

+         pagure.ui.filters.SESSION = self.session

+         pagure.ui.repo.SESSION = self.session

+         pagure.ui.issues.SESSION = self.session

+ 

+         tests.create_projects(self.session)

+         tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)

+ 

+     def _check_star_count(self, data, stars=1):

+         """ Check if the star count is correct or not """

+         output = self.app.get(

+             '/test/', data=data, follow_redirects=True)

+         if stars == 1:

+             self.assertIn(

+                 '<a href="/test/stargazers/" class="btn '

+                 'btn-sm btn-primary">1</a>',

+                 output.data

+             )

+         elif stars == 0:

+             self.assertIn(

+                 '<a href="/test/stargazers/" class="btn '

+                 'btn-sm btn-primary">0</a>',

+                 output.data

+             )

+ 

+     def test_star_project_no_project(self):

+         """ Test the star_project endpoint. """

+ 

+         # No such project

+         output = self.app.post('/test42/star/1')

+         self.assertEqual(output.status_code, 404)

+ 

+     def test_star_project_no_csrf(self):

+         """ Test the star_project endpoint for the case when there

+         is no CSRF token given """

+ 

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+ 

+             data = {}

+             output = self.app.post(

+                 '/test/star/1', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 400)

+ 

+     def test_star_project_invalid_star(self):

+         """ Test the star_project endpoint for invalid star """

+ 

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+             output = self.app.post(

+                 '/test/star/2', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 400)

+             self._check_star_count(data=data, stars=0)

+ 

+     def test_star_project_valid_star(self):

+         """ Test the star_project endpoint for correct star """

+ 

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+ 

+             # try starring the project for pingou

+             output = self.app.post(

+                 '/test/star/1', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You starred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+ 

+             # check home page of project for star count

+             self._check_star_count(data=data, stars=1)

+ 

+             # try unstarring the project for pingou

+             output = self.app.post(

+                 '/test/star/0', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You unstarred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+             self._check_star_count(data=data, stars=0)

+ 

+     def test_repo_stargazers(self):

+         """ Test the repo_stargazers endpoint of pagure.ui.repo """

+ 

+         # make pingou star the project

+         # first create pingou

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+ 

+             output = self.app.post(

+                 '/test/star/1', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You starred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+             self._check_star_count(data=data, stars=1)

+ 

+         # now, test if pingou's name comes in repo stargazers

+         output = self.app.get(

+             '/test/stargazers/'

+         )

+         self.assertIn(

+             '<title>Stargazers of test  - Pagure</title>',

+             output.data

+         )

+         self.assertIn(

+             '<a href="/user/pingou">pingou\n              </a>',

+             output.data

+         )

+ 

+         # make pingou unstar the project

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+ 

+             output = self.app.post(

+                 '/test/star/0', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You unstarred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+             self._check_star_count(data=data, stars=0)

+ 

+         # now, test if pingou's name comes in repo stargazers

+         # it shouldn't because, he just unstarred

+         output = self.app.get(

+             '/test/stargazers/'

+         )

+         self.assertIn(

+             '<title>Stargazers of test  - Pagure</title>',

+             output.data

+         )

+         self.assertNotIn(

+             '<a href="/user/pingou">pingou\n              </a>',

+             output.data

+         )

+ 

+     def test_user_stars(self):

+         """ Test the user_stars endpoint of pagure.ui.app """

+ 

+         # make pingou star the project

+         # first create pingou

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+ 

+             output = self.app.post(

+                 '/test/star/1', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You starred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+             self._check_star_count(data=data, stars=1)

+ 

+         # now, test if the project 'test' comes in pingou's stars

+         output = self.app.get(

+             '/user/pingou/stars'

+         )

+         self.assertIn(

+             "<title>pingou's starred Projects - Pagure</title>",

+             output.data

+         )

+         self.assertIn(

+             '<a href="/test">test</a>\n',

+             output.data

+         )

+ 

+         # make pingou unstar the project

+         user = tests.FakeUser()

+         user.username = 'pingou'

+         with tests.user_set(pagure.APP, user):

+             csrf_token = self.get_csrf()

+             data = {

+                 'csrf_token': csrf_token,

+             }

+             output = self.app.post(

+                 '/test/star/0', data=data, follow_redirects=True)

+             self.assertEqual(output.status_code, 200)

+             self.assertIn(

+                 '</button>\n                      You unstarred '

+                 'this project\n                    </div>',

+                 output.data

+             )

+             self._check_star_count(data=data, stars=0)

+ 

+         # now, test if test's name comes in pingou's stars

+         # it shouldn't because, he just unstarred

+         output = self.app.get(

+             '/user/pingou/stars/'

+         )

+         self.assertIn(

+             "<title>pingou's starred Projects - Pagure</title>",

+             output.data

+         )

+         self.assertNotIn(

+             '<a href="/test">test</a>\n',

+             output.data

+         )

+ 

+ 

+ if __name__ == '__main__':

+     unittest.main(verbosity=2)

@@ -0,0 +1,248 @@ 

+ # coding=utf-8

+ """

+  (c) 2015-2017 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+    Vivek Anand <vivekanand1101@gmail.com>

+ 

+ """

+ 

+ __requires__ = ['SQLAlchemy >= 0.8']

+ import pkg_resources

+ 

+ import unittest

+ import sys

+ import os

+ 

+ sys.path.insert(0, os.path.join(os.path.dirname(

+     os.path.abspath(__file__)), '..'))

+ 

+ import pagure

+ import pagure.lib

+ import tests

+ 

+ 

+ class TestStarProjectLib(tests.SimplePagureTest):

+     ''' Test the star project feature of pagure '''

+ 

+     def setUp(self):

+         """ Set up the environnment for running each star project lib tests """

+         super(TestStarProjectLib, self).setUp()

+         tests.create_projects(self.session)

+ 

+     def test_update_star_project(self):

+         ''' Test the update_star_project endpoint of pagure.lib '''

+ 

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         # test with invalud Star object, should return None

+         msg = pagure.lib.update_star_project(

+             self.session,

+             repo_obj,

+             None,

+             'pingou',

+         )

+         self.session.commit()

+         self.assertEqual(msg, None)

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+         # test starring the project

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         msg = pagure.lib.update_star_project(

+             self.session,

+             repo_obj,

+             '1',

+             'pingou',

+         )

+ 

+         self.session.commit()

+         self.assertEqual(msg, 'You starred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 1)

+ 

+         # test unstarring the project

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         msg = pagure.lib.update_star_project(

+             self.session,

+             repo_obj,

+             '0',

+             'pingou',

+         )

+ 

+         self.session.commit()

+         self.assertEqual(msg, 'You unstarred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+     def test_star_project(self):

+         ''' Test the _star_project endpoint of pagure.lib '''

+ 

+         # test with not all arguments present

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         msg = pagure.lib._star_project(

+             self.session,

+             repo_obj,

+             None

+         )

+         self.session.commit()

+         self.assertEqual(msg, None)

+ 

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._star_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You starred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 1)

+ 

+     def test_unstar_project(self):

+         ''' Test the _unstar_project endpoint of pagure.lib '''

+ 

+         # test with not all arguments present

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         msg = pagure.lib._unstar_project(

+             self.session,

+             repo_obj,

+             None

+         )

+         self.session.commit()

+         self.assertEqual(msg, None)

+ 

+         # the user hasn't starred the project before

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._unstar_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.assertEqual(msg, 'You never starred the project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+         # star it for testing

+         msg = pagure.lib._star_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You starred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 1)

+ 

+         # the user starred and wishes to unstar

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._unstar_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You unstarred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+     def test_get_stargazer_obj(self):

+         ''' Test the _get_stargazer_obj test of pagure.lib '''

+ 

+         # star the project first

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._star_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You starred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 1)

+ 

+         # get the object now

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         star_obj = pagure.lib._get_stargazer_obj(

+             self.session,

+             repo_obj,

+             user_obj

+         )

+         self.assertEqual(isinstance(star_obj, pagure.lib.model.Star), True)

+ 

+         # unstar it and then try to get the object

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._unstar_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You unstarred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+         # we don't store if the user has unstarred, we delete the obj

+         # so, we should get anything back in the query

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         star_obj = pagure.lib._get_stargazer_obj(

+             self.session,

+             repo_obj,

+             user_obj

+         )

+         self.assertEqual(star_obj is None, True)

+ 

+     def test_has_starred(self):

+         ''' Test the has_starred endpoint of pagure.lib '''

+ 

+         # star the project

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._star_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You starred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 1)

+ 

+         has_starred = pagure.lib.has_starred(

+             self.session,

+             repo_obj,

+             'pingou'

+         )

+         self.assertEqual(has_starred is True, True)

+ 

+         # unstar it and then test for has_starred

+         repo_obj = pagure.lib._get_project(self.session, 'test')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         msg = pagure.lib._unstar_project(

+             self.session,

+             repo_obj,

+             user_obj,

+         )

+         self.session.commit()

+         self.assertEqual(msg, 'You unstarred this project')

+         user_obj = pagure.lib.get_user(self.session, 'pingou')

+         self.assertEqual(len(user_obj.stars), 0)

+ 

+         # check now, it should return False

+         has_starred = pagure.lib.has_starred(

+             self.session,

+             repo_obj,

+             'pingou'

+         )

+         self.assertEqual(has_starred is False, True)

+ 

+ 

+ if __name__ == '__main__':

+     unittest.main(verbosity=2)

  1. I know this was low priority but, i got tired of asking people to star pagure on github.
  2. Unit tests are left, i will add once i fix them
  3. Do we want to keep the name to "star"? I can change, if needed

rebased

6 years ago

1 new commit added

  • star repo: index project_id, add ondelete cascade in models
6 years ago

I think it would be a no brainer to read the code if you add else here.

This function is used to star or unstar a project. Maybe it should be documented in the docstring since the name of the function is not making it clear.

I am not sure the title is needed, I think it is obvious.

You could just use Star this project as title

Here the title could just be Unstar this project

Added a few minor comments.

I get your point but, i don't really like the unnecessary else statement :/ I even remove them if the if part is returning :(

It's normally considered cleaner to have as little return statement as possible.
So in this case I would agree with @cverna and advice that we use an if/else construct and have a single return msg at the end.

Should we check that stargazer_obj exists before we delete it?

Do we have a way to name that constraint as you did in the alembic migration?

We'll need tests for all this :)

rebased

6 years ago

1 new commit added

  • star repo: check the object exits before deleting
6 years ago

8 new commits added

  • star repo: check the object exists before deleting
  • star repo: update view - star_project docstring
  • star repo: remove titles, change return msgs
  • star repo: use if/else construct in update_star function
  • star repo: name the unique constraint in model as well
  • star repo: index project_id, add ondelete cascade in models
  • star project: Add titles to specify what actions buttons are meant for
  • Star a project
6 years ago

:+1: this is a feature that was required :smile:

rebased

6 years ago

1 new commit added

  • star_project: update alembic down revision after date_modified in projects
6 years ago

rebased

6 years ago

2 new commits added

  • star repo: Check for url safety only when referrer is there
  • Unit test: add ui tests for star project
6 years ago

@pingou , @farhaan , i have added tests but, my unit tests are not fully fixed, there are some errors which i doubt is related to star project. Please check before merging :p

12 new commits added

  • star repo: Check for url safety only when referrer is there
  • Unit test: add ui tests for star project
  • Unit test: add lib tests for star project
  • star_project: update alembic down revision after date_modified in projects
  • star repo: check the object exists before deleting
  • star repo: update view - star_project docstring
  • star repo: remove titles, change return msgs
  • star repo: use if/else construct in update_star function
  • star repo: name the unique constraint in model as well
  • star repo: index project_id, add ondelete cascade in models
  • star project: Add titles to specify what actions buttons are meant for
  • Star a project
6 years ago

rebased

6 years ago

missing the star arg from the docstring.

Why not have star as a boolean here ?

missing the return docstring

missing the return docstring

missing the return docstring

need to update the repo and user docstring

missing the return docstring

maybe use the same convention as above and put the type in the arg description

I think it would be nicer to have star as a boolean.

same here star would be a good boolean :)

Maybe you put the type in the arg description. And elsewhere we use arg instead of param

I would change this for a boolean

identation feels odd here

if star is a boolean you can drop this

I would maybe create a separate class for the ui testing so that you can take advantage of the setUp method to star the project

rebased

6 years ago

:thumbsup: :D

Needs a rebase too :)

rebased

6 years ago

rebased

6 years ago

@vivekanand1101 http://paste.opensuse.org/66275115 :(

This is on my laptop 1080p resolution on a 13.3" screen

this is how it looks in mine. http://paste.opensuse.org/20249430 . If you want to fix (pls :cry: ) you already have access to my fork.

1 new commit added

  • Give the star button his own
6 years ago

I was just trying to test this, did both of you tried the alembic migration on postgresql? I'm running into a weird NotImplementedError error

I had to remove sa.MetaData(), to get it working here :(

called alembic with PAGURE_CONFIG... or did you adjust the default_config?

14 new commits added

  • Give the star button his own
  • star project: fix docstrings in lib and ui
  • star repo: Check for url safety only when referrer is there
  • Unit test: add ui tests for star project
  • Unit test: add lib tests for star project
  • star_project: update alembic down revision after date_modified in projects
  • star repo: check the object exists before deleting
  • star repo: update view - star_project docstring
  • star repo: remove titles, change return msgs
  • star repo: use if/else construct in update_star function
  • star repo: name the unique constraint in model as well
  • star repo: index project_id, add ondelete cascade in models
  • star project: Add titles to specify what actions buttons are meant for
  • Star a project
6 years ago

rebased

6 years ago

aouch, quite a few tests are failing here :(
Do they work for you?

@vivekanand1101 do you need help with fixing the tests ?

@vivekanand1101 do you need help with fixing the tests ?

I got most of them passing, seeing just one in the current run

rebased

6 years ago

Pull-Request has been merged by pingou

6 years ago