from unittest.mock import patch from urllib.parse import quote from django.conf import settings from django.contrib.auth import SESSION_KEY from django.contrib.auth.models import User from django.test import TestCase from django.urls import reverse from .models import Author, Paper, Writes def create_test_data(): User.objects.create_user('alice', 'alice@example.com', '1234') Author.objects.bulk_create([ Author(id=i, name=f'A{i}', n_citation=c) for i, c in enumerate([4, 5, 3]) ]) papers = Paper.objects.bulk_create([ Paper(id=i, title=f'P{i}', year=2021, abstract='', n_citation=3 - i) for i in range(3) ]) writes = [[0, 1], [1, 2], [0, 2]] Writes.objects.bulk_create(reversed([ Writes(author_id=a, paper_id=p, order=r + 1) for p, authors in enumerate(writes) for r, a in enumerate(authors) ])) for i, r in enumerate([[], [0], [0, 1]]): papers[i].references.set(r) class LoginViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def test_get(self): response = self.client.get(reverse('rank:login')) self.assertTemplateUsed(response, 'rank/login.html') def test_get_already_login(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) response = self.client.get(reverse('rank:login')) self.assertRedirects(response, reverse('rank:index')) def test_ok(self): data = {'username': 'alice', 'password': '1234'} response = self.client.post(reverse('rank:login'), data) self.assertEqual('1', self.client.session[SESSION_KEY]) self.assertRedirects(response, reverse('rank:index')) def test_redirect(self): redirect_url = reverse('rank:index') + '?foo=123&bar=abc' login_url = '{}?next={}'.format(reverse('rank:login'), quote(redirect_url)) response = self.client.get(login_url) self.assertContains(response, 'action="{}"'.format(login_url)) data = {'username': 'alice', 'password': '1234'} response = self.client.post(login_url, data) self.assertRedirects(response, redirect_url) def test_wrong_username_or_password(self): data = {'username': 'alice', 'password': '5678'} response = self.client.post(reverse('rank:login'), data) self.assertTemplateUsed(response, 'rank/login.html') self.assertContains(response, '用户名或密码错误') class RegisterViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def test_get(self): response = self.client.get(reverse('rank:register')) self.assertTemplateUsed(response, 'rank/register.html') def test_invalid_username(self): data = {'username': '@#%', 'password': '1234', 'password2': '1234'} response = self.client.post(reverse('rank:register'), data) self.assertEqual('用户名只能包含字母、数字和下划线', response.context['message']) def test_username_already_exists(self): data = {'username': 'alice', 'password': '1234', 'password2': '1234'} response = self.client.post(reverse('rank:register'), data) self.assertEqual('用户名已存在', response.context['message']) def test_passwords_not_match(self): data = {'username': 'cindy', 'password': '1234', 'password2': '5678'} response = self.client.post(reverse('rank:register'), data) self.assertEqual('两次密码不一致', response.context['message']) def test_ok(self): data = {'username': 'bob', 'password': '1234', 'password2': '1234', 'name': '', 'email': ''} response = self.client.post(reverse('rank:register'), data) self.assertRedirects(response, reverse('rank:login')) self.assertTrue(User.objects.filter(username='bob').exists()) class SearchPaperViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def setUp(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) @patch('gnnrec.kgrec.recall.recall', return_value=(None, [1, 2])) def test_ok(self, recall): response = self.client.get(reverse('rank:search-paper'), data={'q': 'xxx'}) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'rank/search_paper.html') self.assertQuerysetEqual(response.context['object_list'], ['P1', 'P2'], transform=str) recall.assert_called_with(None, 'xxx', settings.PAGE_SIZE) class PaperDetailViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def setUp(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) def test_ok(self): response = self.client.get(reverse('rank:paper-detail', args=(1,))) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'rank/paper_detail.html') self.assertContains(response, 'P1') def test_not_found(self): response = self.client.get(reverse('rank:paper-detail', args=(999,))) self.assertEqual(404, response.status_code) class AuthorDetailViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def setUp(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) def test_ok(self): response = self.client.get(reverse('rank:author-detail', args=(0,))) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'rank/author_detail.html') self.assertContains(response, 'A0') self.assertContains(response, '4 citations') self.assertQuerysetEqual(response.context['object_list'], ['P0', 'P2'], transform=str) def test_not_found(self): response = self.client.get(reverse('rank:author-detail', args=(999,))) self.assertEqual(404, response.status_code) class SearchAuthorViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def setUp(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) def test_ok(self): response = self.client.get(reverse('rank:search-author'), data={'q': 'A0'}) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'rank/search_author.html') self.assertQuerysetEqual(response.context['object_list'], ['A0'], transform=str) def test_no_result(self): response = self.client.get(reverse('rank:search-author'), data={'q': 'xxx'}) self.assertQuerysetEqual(response.context['object_list'], [], transform=str) self.assertContains(response, '未找到学者xxx') class AuthorRankViewTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def setUp(self): self.client.post(reverse('rank:login'), data={'username': 'alice', 'password': '1234'}) @patch('gnnrec.kgrec.rank.rank', return_value=(None, [1, 0])) def test_ok(self, rank): response = self.client.get(reverse('rank:author-rank'), data={'q': 'xxx'}) self.assertEqual(200, response.status_code) self.assertTemplateUsed(response, 'rank/author_rank.html') self.assertQuerysetEqual(response.context['object_list'], ['A1', 'A0'], transform=str) rank.assert_called_with(None, 'xxx') def test_not_login(self): self.client.get(reverse('rank:logout')) response = self.client.get(reverse('rank:author-rank'), {'q': 'xxx'}) self.assertRedirects(response, '{}?next={}'.format( reverse('rank:login'), quote(reverse('rank:author-rank') + '?q=xxx') )) class WritesModelTests(TestCase): @classmethod def setUpTestData(cls): create_test_data() def test_ordering(self): writes = Writes.objects.filter(paper_id=2) expected = ['(author_id=0, paper_id=2, order=1)', '(author_id=2, paper_id=2, order=2)'] self.assertQuerysetEqual(writes, expected, transform=str)