diff --git a/later42/templates/about.html b/later42/templates/about.html
new file mode 100644
index 0000000..0fc9f20
--- /dev/null
+++ b/later42/templates/about.html
@@ -0,0 +1,6 @@
+{% extends 'base.html' %}
+
+{% block content %}
+ {% include 'about_include.html' %}
+ {% include 'faq_include.html' %}
+{% endblock %}
diff --git a/later42/templates/about_include.html b/later42/templates/about_include.html
new file mode 100644
index 0000000..9379eb8
--- /dev/null
+++ b/later42/templates/about_include.html
@@ -0,0 +1,24 @@
+
Сервис для сохранения ссылок
+
+
+ Сохраняйте заинтересовавшие вас ссылки для последующего вдумчивого чтения.
+
+
+ В наше спешащее время мы не успеваем читать вдумчиво и спокойно. Пролистываем тонны информации за день.
+ Теперь можно не спешить, а просто отложить ссылку на интересную статью, чтобы потом вернуться к ней и в спокойной
+ обстановке вдумчиво ее прочитать.
+
+
+Как это работает
+
+
+ Для начала работы нужно только зарегистрироваться и получить API ключ.
+
+
+ Дальше устанавливаете Команду "Shortcut" в ваше iOS или MacOS устройство и через меню "Поделиться" добавляете ссылку.
+
+
+ При первом запуске Команда спросит ваш API ключ. Дальше все будет работать прозрачно и без лишних вопросов.
+
+
+
diff --git a/later42/templates/base.html b/later42/templates/base.html
index 2af7d45..2ee4029 100644
--- a/later42/templates/base.html
+++ b/later42/templates/base.html
@@ -29,6 +29,7 @@
-
© dntsk.dev, 2022
+
Later 42 by
dntsk.dev, 2022
+
v0.0.1
diff --git a/later42/templates/docs.html b/later42/templates/docs.html
deleted file mode 100644
index 71df6fe..0000000
--- a/later42/templates/docs.html
+++ /dev/null
@@ -1,2 +0,0 @@
-Test content block
-
diff --git a/later42/templates/faq_include.html b/later42/templates/faq_include.html
new file mode 100644
index 0000000..94265a3
--- /dev/null
+++ b/later42/templates/faq_include.html
@@ -0,0 +1,9 @@
+{% load static %}
+Часто задаваемые вопросы:
+
+Где взять команду Shortcuts для iOS/MacOS?
+Скачать команду.
+После установки команды и первого запуска из меню "Поделиться" вас попросит ввести ваш API ключ. Взять его вы
+ можете в вашем профиле.
+Будет ли поддержка Android?
+Да, поддержка устройств на OS Android планируется через бота в Telegram. Сроки пока не известны.
diff --git a/later42/templates/index.html b/later42/templates/index.html
index 11e6af0..84dfb2d 100644
--- a/later42/templates/index.html
+++ b/later42/templates/index.html
@@ -25,6 +25,6 @@
У вас нет сохраненных ссылок
{% elif not user.is_authenticated %}
- {% include 'docs.html' %}
+ {% include 'about_include.html' %}
{% endif %}
{% endblock %}
diff --git a/later42/templates/profile.html b/later42/templates/profile.html
index e373a8a..26b2546 100644
--- a/later42/templates/profile.html
+++ b/later42/templates/profile.html
@@ -36,12 +36,12 @@
{{ token }}
{% else %}
{% endif %}
diff --git a/later42/tests/__init__.py b/later42/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/later42/tests/views/__init__.py b/later42/tests/views/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/later42/tests/views/test_api.py b/later42/tests/views/test_api.py
new file mode 100644
index 0000000..c354634
--- /dev/null
+++ b/later42/tests/views/test_api.py
@@ -0,0 +1,36 @@
+from django.contrib.auth.models import User
+from django.test import TestCase, Client
+from django.urls import reverse
+from rest_framework.authtoken.models import Token
+from rest_framework.test import APIClient
+
+from later42.models.urls import URL
+
+
+class ApiTests(TestCase):
+ def setUp(self) -> None:
+ self.username = 'testuser1'
+ self.email = 'testuser1@email.com'
+ self.password = 'password1234567QWERTY'
+ self.user = User.objects.create(
+ username=self.username,
+ email=self.email
+ )
+ self.user.set_password(self.password)
+ self.user.save()
+
+ self.url = 'https://google.com'
+
+ self.c = Client()
+ self.c.login(username=self.username, password=self.password)
+ self.assertTrue(self.user.is_authenticated)
+ self.token = Token.objects.create(user=self.user)
+
+ def test_url_create(self):
+ token = Token.objects.get(user=self.user)
+ client = APIClient()
+ client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
+ response = client.post(reverse('urls') + f'?url={self.url}')
+ assert response.status_code == 200
+ self.assertContains(response, 'success')
+ self.assertEqual(URL.objects.count(), 1)
diff --git a/later42/tests/views/test_api_token.py b/later42/tests/views/test_api_token.py
new file mode 100644
index 0000000..c3943c9
--- /dev/null
+++ b/later42/tests/views/test_api_token.py
@@ -0,0 +1,36 @@
+from django.contrib.auth.models import User
+from django.test import TestCase, Client
+from django.urls import reverse
+from rest_framework.authtoken.models import Token
+
+
+class ApiKeyTests(TestCase):
+ def setUp(self) -> None:
+ self.username = 'testuser1'
+ self.email = 'testuser1@email.com'
+ self.password = 'password1234567QWERTY'
+ self.user = User.objects.create(
+ username=self.username,
+ email=self.email
+ )
+ self.user.set_password(self.password)
+ self.user.save()
+
+ self.c = Client()
+ self.c.login(username=self.username, password=self.password)
+ self.assertTrue(self.user.is_authenticated)
+ self.response = self.c.get(reverse('api_token'))
+
+ def test_api_key_creation(self):
+ assert self.response.status_code == 302
+ assert self.response.url == '/profile/'
+
+ def test_api_key_created(self):
+ token = Token.objects.get(user=self.user)
+ assert token is not None
+
+ def test_api_key_reset(self):
+ token_old = Token.objects.get(user=self.user)
+ self.response = self.c.get(reverse('api_token'))
+ token_new = Token.objects.get(user=self.user)
+ assert token_old != token_new
diff --git a/later42/tests/views/test_index.py b/later42/tests/views/test_index.py
new file mode 100644
index 0000000..727cebd
--- /dev/null
+++ b/later42/tests/views/test_index.py
@@ -0,0 +1,33 @@
+from django.contrib.auth.models import User
+from django.test import TestCase, Client
+from django.urls import reverse
+from rest_framework.authtoken.models import Token
+
+from later42.models.urls import URL
+
+
+class IndexTests(TestCase):
+ def setUp(self) -> None:
+ self.username = 'testuser1'
+ self.email = 'testuser1@email.com'
+ self.password = 'password1234567QWERTY'
+ self.user = User.objects.create(
+ username=self.username,
+ email=self.email
+ )
+ self.user.set_password(self.password)
+ self.user.save()
+
+ self.c = Client()
+ self.c.login(username=self.username, password=self.password)
+ self.assertTrue(self.user.is_authenticated)
+
+ def test_url_delete(self):
+ url = URL.objects.create(
+ url='https://www.google.com/',
+ user=self.user
+ )
+ url.save()
+ self.c.delete(reverse('delete', kwargs={'url_id': url.id}))
+ url = URL.objects.filter(id=url.id)
+ assert len(url) == 0
diff --git a/later42/tests/views/test_login.py b/later42/tests/views/test_login.py
new file mode 100644
index 0000000..4314c1e
--- /dev/null
+++ b/later42/tests/views/test_login.py
@@ -0,0 +1,41 @@
+from django.contrib.auth.models import User
+from django.test import TestCase, Client
+from django.urls import reverse
+
+
+class LoginPageTests(TestCase):
+ def setUp(self) -> None:
+ self.username = 'testuser1'
+ self.email = 'testuser1@email.com'
+ self.password = 'password1234567QWERTY'
+ self.user = User.objects.create(
+ username=self.username,
+ email=self.email
+ )
+ self.user.set_password(self.password)
+ self.user.save()
+
+ self.c = Client()
+ self.c.login(username=self.username, password=self.password)
+ self.assertTrue(self.user.is_authenticated)
+
+ def test_login_page(self):
+ response = self.client.get(reverse('login'))
+ assert response.status_code == 200
+
+ def test_index_page_after_login(self):
+ response = self.c.get(reverse('index'))
+ assert response.status_code == 200
+ assert response.context['user'].is_authenticated
+ self.assertTemplateUsed(response, 'index.html')
+ self.assertContains(response, '/accounts/logout/')
+
+ def test_profile_page_template(self):
+ response = self.c.get(reverse('profile'))
+ assert response.status_code == 200
+ self.assertTemplateUsed(response, 'profile.html')
+
+ def test_api_key_creation_button(self):
+ response = self.c.get(reverse('profile'))
+ assert response.status_code == 200
+ self.assertContains(response, 'id="createbutton"')
diff --git a/later42/tests/views/test_pages.py b/later42/tests/views/test_pages.py
new file mode 100644
index 0000000..966ec07
--- /dev/null
+++ b/later42/tests/views/test_pages.py
@@ -0,0 +1,19 @@
+from django.test import TestCase
+
+from django.urls import reverse
+
+
+class PageTests(TestCase):
+ def test_index_page_url(self):
+ response = self.client.get(reverse('index'))
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, template_name='index.html')
+
+ def test_about_page_url(self):
+ response = self.client.get(reverse('about'))
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, template_name='about.html')
+
+ def test_profile_page_url_redirect(self):
+ response = self.client.get(reverse('profile'))
+ self.assertEqual(response.status_code, 302)
diff --git a/later42/tests/views/test_signup.py b/later42/tests/views/test_signup.py
new file mode 100644
index 0000000..ddf1925
--- /dev/null
+++ b/later42/tests/views/test_signup.py
@@ -0,0 +1,33 @@
+from django.test import TestCase
+
+from django.contrib.auth import get_user_model
+from django.urls import reverse
+
+
+class SignUpPageTests(TestCase):
+ def setUp(self) -> None:
+ self.username = 'testuser'
+ self.email = 'testuser@email.com'
+ self.password = 'password1234567QWERTY'
+
+ def test_signup_page_url(self):
+ response = self.client.get(reverse('signup'))
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, template_name='signup.html')
+
+ def test_signup_page_view_name(self):
+ response = self.client.get(reverse('signup'))
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, template_name='signup.html')
+
+ def test_signup_form(self):
+ response = self.client.post(reverse('signup'), data={
+ 'username': self.username,
+ 'email': self.email,
+ 'password1': self.password,
+ 'password2': self.password
+ })
+ self.assertEqual(response.status_code, 302)
+
+ users = get_user_model().objects.all()
+ self.assertEqual(users.count(), 1)
diff --git a/later42/urls.py b/later42/urls.py
index 5beb9ad..21af61f 100644
--- a/later42/urls.py
+++ b/later42/urls.py
@@ -22,7 +22,7 @@ from django.contrib.auth.views import LoginView
from rest_framework import routers, serializers, viewsets
from later42.forms import CustomLoginForm
-from later42.views import index, profile, api, api_token, signup
+from later42.views import index, profile, api, api_token, signup, about
class UserSerializer(serializers.HyperlinkedModelSerializer):
@@ -45,9 +45,10 @@ urlpatterns = [
path("accounts/login/", LoginView.as_view(authentication_form=CustomLoginForm), name="login"),
path('accounts/', include('django_registration.backends.activation.urls')),
path("accounts/", include("django.contrib.auth.urls")),
- path('api/url/', api.URL.as_view(), name='urls'),
- path('', index.get, name='index'),
- path('delete/', index.delete, name='delete'),
path('profile/', profile.get, name='profile'),
+ path('api/url/', api.URL.as_view(), name='urls'),
+ path('delete/', index.delete, name='delete'),
path('api_token/', api_token.create, name='api_token'),
+ path('', index.get, name='index'),
+ path('about/', about.get, name='about'),
]
diff --git a/later42/views/about.py b/later42/views/about.py
new file mode 100644
index 0000000..8d35a2d
--- /dev/null
+++ b/later42/views/about.py
@@ -0,0 +1,5 @@
+from django.shortcuts import render
+
+
+def get(request):
+ return render(request, 'about.html')
diff --git a/later42/views/api_token.py b/later42/views/api_token.py
index c5c25fe..2c0e16a 100644
--- a/later42/views/api_token.py
+++ b/later42/views/api_token.py
@@ -1,13 +1,13 @@
+from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from rest_framework.authtoken.models import Token
+@login_required
def create(request):
token = Token.objects.filter(user=request.user)
- try:
+ if len(token) > 0:
token.delete()
- except:
- pass
token = Token.objects.create(user=request.user)
token.save()
- return redirect('profile')
\ No newline at end of file
+ return redirect('profile')
diff --git a/later42/views/signup.py b/later42/views/signup.py
index 59ad96e..4ac27d7 100644
--- a/later42/views/signup.py
+++ b/later42/views/signup.py
@@ -18,4 +18,4 @@ def register(request):
return redirect('index')
else:
form = SignUpForm()
- return render(request, 'signup.html', {'form': form})
\ No newline at end of file
+ return render(request, 'signup.html', {'form': form})