<commit_before># -*- coding: utf-8 -*-
from nose.tools import *  # flake8: noqa

from website.models import NodeLog
from website.project.model import Auth
from website.util import permissions

from api.base.settings.defaults import API_BASE

from tests.base import ApiTestCase
from tests.factories import (
    ProjectFactory,
    AuthUserFactory,
)
from tests.utils import assert_logs, assert_not_logs


class NodeCRUDTestCase(ApiTestCase):

    def setUp(self):
        super(NodeCRUDTestCase, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()

        self.title = 'Cool Project'
        self.new_title = 'Super Cool Project'
        self.description = 'A Properly Cool Project'
        self.new_description = 'An even cooler project'
        self.category = 'data'
        self.new_category = 'project'

        self.public_project = ProjectFactory(title=self.title,
                                             description=self.description,
                                             category=self.category,
                                             is_public=True,
                                             creator=self.user)

        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id)

        self.private_project = ProjectFactory(title=self.title,
                                              description=self.description,
                                              category=self.category,
                                              is_public=False,
                                              creator=self.user)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id)

        self.fake_url = '/{}nodes/{}/'.format(API_BASE, '12345')


def make_node_payload(node, attributes):
    return {
        'data': {
            'id': node._id,
            'type': 'nodes',
            'attributes': attributes,
        }
    }


class TestContributorDetail(NodeCRUDTestCase):
    def setUp(self):
        super(TestContributorDetail, self).setUp()

        self.public_url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.public_project, self.user._id)
        self.private_url_base = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.private_project._id, '{}')
        self.private_url = self.private_url_base.format(self.user._id)

    def test_get_public_contributor_detail(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['id'], '{}-{}'.format(self.public_project._id, self.user._id))

    def test_get_private_node_contributor_detail_contributor_auth(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['id'], '{}-{}'.format(self.private_project, self.user._id))

    def test_get_private_node_contributor_detail_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_get_private_node_contributor_detail_not_logged_in(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)

    def test_get_private_node_non_contributor_detail_contributor_auth(self):
        res = self.app.get(self.private_url_base.format(self.user_two._id), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_get_private_node_invalid_user_detail_contributor_auth(self):
        res = self.app.get(self.private_url_base.format('invalid'), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_unregistered_contributor_detail_show_up_as_name_associated_with_project(self):
        project = ProjectFactory(creator=self.user, public=True)
        project.add_unregistered_contributor('<NAME>', '<EMAIL>', auth=Auth(self.user), save=True)
        unregistered_contributor = project.contributors[1]
        url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, unregistered_contributor._id)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], '<NAME>')
        assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), '<NAME>')

        project_two = ProjectFactory(creator=self.user, public=True)
        project_two.add_unregistered_contributor('<NAME>', '<EMAIL>', auth=Auth(self.user), save=True)
        url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_two._id, unregistered_contributor._id)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 200)

        assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], '<NAME>')
        assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), '<NAME>')


class TestNodeContributorUpdate(ApiTestCase):
    def setUp(self):
        super(TestNodeContributorUpdate, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()

        self.project = ProjectFactory(creator=self.user)
        self.project.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)

        self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user._id)
        self.url_contributor = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id)

    def test_node_update_invalid_data(self):
        res = self.app.put_json_api(self.url_creator, "Incorrect data", auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")

        res = self.app.put_json_api(self.url_creator, ["Incorrect data"], auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")
<commit_msg>Add tests for re-ordering contributor functionality<commit_after># -*- coding: utf-8 -*-
from nose.tools import *  # flake8: noqa

from website.models import NodeLog
from website.project.model import Auth
from website.util import permissions

from api.base.settings.defaults import API_BASE

from tests.base import ApiTestCase
from tests.factories import (
    ProjectFactory,
    AuthUserFactory,
)
from tests.utils import assert_logs, assert_not_logs


class NodeCRUDTestCase(ApiTestCase):

    def setUp(self):
        super(NodeCRUDTestCase, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()

        self.title = 'Cool Project'
        self.new_title = 'Super Cool Project'
        self.description = 'A Properly Cool Project'
        self.new_description = 'An even cooler project'
        self.category = 'data'
        self.new_category = 'project'

        self.public_project = ProjectFactory(title=self.title,
                                             description=self.description,
                                             category=self.category,
                                             is_public=True,
                                             creator=self.user)

        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id)

        self.private_project = ProjectFactory(title=self.title,
                                              description=self.description,
                                              category=self.category,
                                              is_public=False,
                                              creator=self.user)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id)

        self.fake_url = '/{}nodes/{}/'.format(API_BASE, '12345')


def make_node_payload(node, attributes):
    return {
        'data': {
            'id': node._id,
            'type': 'nodes',
            'attributes': attributes,
        }
    }


class TestContributorDetail(NodeCRUDTestCase):
    def setUp(self):
        super(TestContributorDetail, self).setUp()

        self.public_url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.public_project, self.user._id)
        self.private_url_base = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.private_project._id, '{}')
        self.private_url = self.private_url_base.format(self.user._id)

    def test_get_public_contributor_detail(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['id'], '{}-{}'.format(self.public_project._id, self.user._id))

    def test_get_private_node_contributor_detail_contributor_auth(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['id'], '{}-{}'.format(self.private_project, self.user._id))

    def test_get_private_node_contributor_detail_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_get_private_node_contributor_detail_not_logged_in(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)

    def test_get_private_node_non_contributor_detail_contributor_auth(self):
        res = self.app.get(self.private_url_base.format(self.user_two._id), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_get_private_node_invalid_user_detail_contributor_auth(self):
        res = self.app.get(self.private_url_base.format('invalid'), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_unregistered_contributor_detail_show_up_as_name_associated_with_project(self):
        project = ProjectFactory(creator=self.user, public=True)
        project.add_unregistered_contributor('<NAME>', '<EMAIL>', auth=Auth(self.user), save=True)
        unregistered_contributor = project.contributors[1]
        url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, unregistered_contributor._id)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], '<NAME>')
        assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), '<NAME>')

        project_two = ProjectFactory(creator=self.user, public=True)
        project_two.add_unregistered_contributor('<NAME>', '<EMAIL>', auth=Auth(self.user), save=True)
        url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_two._id, unregistered_contributor._id)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 200)

        assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], '<NAME>')
        assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), '<NAME>')


class TestNodeContributorOrdering(ApiTestCase):
    def setUp(self):
        super(TestNodeContributorOrdering, self).setUp()
        self.contributors = [AuthUserFactory() for number in range(1, 10)]
        self.user_one = AuthUserFactory()

        self.project = ProjectFactory(creator=self.user_one)
        for contributor in self.contributors:
            self.project.add_contributor(
                contributor,
                permissions=[permissions.READ, permissions.WRITE],
                visible=True,
                save=True
            )

        self.contributors.insert(0, self.user_one)
        self.base_contributor_url = '/{}nodes/{}/contributors/'.format(API_BASE, self.project._id)
        self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_one._id)
        self.contributor_urls = ['/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, contributor._id)
            for contributor in self.contributors]
        self.last_position = len(self.contributors) - 1

    @staticmethod
    def _get_contributor_user_id(contributor):
        return contributor['embeds']['users']['data']['id']

    def test_initial_order(self):
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        found_contributors = False
        for i in range(0, len(self.contributors)):
            assert_equal(self.contributors[i]._id, self._get_contributor_user_id(contributor_list[i]))
            assert_equal(i, contributor_list[i]['attributes']['index'])
            found_contributors = True
        assert_true(found_contributors, "Did not compare any contributors.")

    def test_move_top_contributor_down_one(self):
        contributor_to_move = self.contributors[0]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_contributor = self.contributors[1]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': 1
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[1]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id)

    def test_move_second_contributor_up_one_to_top(self):
        contributor_to_move = self.contributors[1]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_first_contributor = self.contributors[0]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': 0
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[1]), former_first_contributor._id)

    def test_move_top_contributor_down_to_bottom(self):
        contributor_to_move = self.contributors[0]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_contributor = self.contributors[1]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': self.last_position
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[self.last_position]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id)

    def test_move_bottom_contributor_up_to_top(self):
        contributor_to_move = self.contributors[self.last_position]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_to_last_contributor = self.contributors[self.last_position - 1]

        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': 0
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move)
        assert_equal(
            self._get_contributor_user_id(contributor_list[self.last_position]),
            former_second_to_last_contributor._id
        )

    def test_move_second_to_last_contributor_down_past_bottom(self):
        contributor_to_move = self.contributors[self.last_position - 1]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_last_contributor = self.contributors[self.last_position]

        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': self.last_position + 10
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[self.last_position]), contributor_to_move)
        assert_equal(
            self._get_contributor_user_id(contributor_list[self.last_position - 1]),
            former_last_contributor._id
        )

    def test_move_top_contributor_down_to_second_to_last_position_with_negative_numbers(self):
        contributor_to_move = self.contributors[0]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_contributor = self.contributors[1]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': -1
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth)
        assert_equal(res_patch.status_code, 200)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[self.last_position - 1]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id)

    def test_write_contributor_fails_to_move_top_contributor_down_one(self):
        contributor_to_move = self.contributors[0]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_contributor = self.contributors[1]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': 1
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, auth=former_second_contributor.auth, expect_errors=True)
        assert_equal(res_patch.status_code, 403)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[1]), former_second_contributor._id)

    def test_non_authenticated_fails_to_move_top_contributor_down_one(self):
        contributor_to_move = self.contributors[0]._id
        contributor_id = '{}-{}'.format(self.project._id, contributor_to_move)
        former_second_contributor = self.contributors[1]
        url = '{}{}/'.format(self.base_contributor_url, contributor_to_move)
        data = {
            'data': {
                'id': contributor_id,
                'type': 'contributors',
                'attributes': {
                    'index': 1
                }
            }
        }
        res_patch = self.app.patch_json_api(url, data, expect_errors=True)
        assert_equal(res_patch.status_code, 401)
        self.project.reload()
        res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth)
        assert_equal(res.status_code, 200)
        contributor_list = res.json['data']
        assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move)
        assert_equal(self._get_contributor_user_id(contributor_list[1]), former_second_contributor._id)


class TestNodeContributorUpdate(ApiTestCase):
    def setUp(self):
        super(TestNodeContributorUpdate, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()

        self.project = ProjectFactory(creator=self.user)
        self.project.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)

        self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user._id)
        self.url_contributor = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id)

    def test_node_update_invalid_data(self):
        res = self.app.put_json_api(self.url_creator, "Incorrect data", auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")

        res = self.app.put_json_api(self.url_creator, ["Incorrect data"], auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")

{'fraction_non_alphanumeric': 0.12651166751831033, 'fraction_numerical': 0.007324135581672628, 'mean_word_length': 2.867116746253911, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6956339', 'n_tokens_mistral': 7360, 'n_tokens_neox': 6952, 'n_words': 936}