mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-09-17 09:42:29 +03:00
Persist raw data in browseable api when do POST
This commit is contained in:
parent
59ae95b22f
commit
853e1052cb
|
@ -3,3 +3,4 @@ pytest>=6.2.0,<8.0
|
||||||
pytest-cov>=4.0.0,<5.0
|
pytest-cov>=4.0.0,<5.0
|
||||||
pytest-django>=4.5.2,<5.0
|
pytest-django>=4.5.2,<5.0
|
||||||
importlib-metadata<5.0
|
importlib-metadata<5.0
|
||||||
|
selenium==4.7.2
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('form').ajaxForm();
|
$('form').ajaxForm();
|
||||||
|
persistPostRawDataForm()
|
||||||
});
|
});
|
||||||
|
|
22
rest_framework/static/rest_framework/js/store-data-form.js
Normal file
22
rest_framework/static/rest_framework/js/store-data-form.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* Preserve form's raw input after do POST
|
||||||
|
*/
|
||||||
|
function persistPostRawDataForm() {
|
||||||
|
var formContainerId = '#post-generic-content-form'
|
||||||
|
var $form = $(`${formContainerId} form`)
|
||||||
|
var $formInput = $(`${formContainerId} textarea`);
|
||||||
|
var localStorageKey = 'rawDataSubmitted'
|
||||||
|
var formAction = $form.attr('action')
|
||||||
|
|
||||||
|
$form.submit(function () {
|
||||||
|
var data = sessionStorage.getItem(localStorageKey)
|
||||||
|
data = data ? JSON.parse(data) : {}
|
||||||
|
data[formAction] = $formInput.val()
|
||||||
|
sessionStorage.setItem(localStorageKey, JSON.stringify(data))
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sessionStorage.getItem(localStorageKey)) {
|
||||||
|
var data = JSON.parse(sessionStorage.getItem(localStorageKey))
|
||||||
|
$formInput.text(data[formAction])
|
||||||
|
};
|
||||||
|
}
|
|
@ -295,6 +295,7 @@
|
||||||
</script>
|
</script>
|
||||||
<script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
|
<script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
|
||||||
<script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
|
<script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
|
||||||
|
<script src="{% static "rest_framework/js/store-data-form.js" %}"></script>
|
||||||
<script src="{% static "rest_framework/js/csrf.js" %}"></script>
|
<script src="{% static "rest_framework/js/csrf.js" %}"></script>
|
||||||
<script src="{% static "rest_framework/js/bootstrap.min.js" %}"></script>
|
<script src="{% static "rest_framework/js/bootstrap.min.js" %}"></script>
|
||||||
<script src="{% static "rest_framework/js/prettify-min.js" %}"></script>
|
<script src="{% static "rest_framework/js/prettify-min.js" %}"></script>
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.firefox.webdriver import WebDriver
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.routers import SimpleRouter
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
|
from rest_framework.utils import json
|
||||||
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
from tests.models import BasicModel
|
||||||
|
|
||||||
from .views import BasicModelWithUsersViewSet, OrganizationPermissions
|
from .views import BasicModelWithUsersViewSet, OrganizationPermissions
|
||||||
|
|
||||||
|
@ -99,3 +107,90 @@ class NoDropdownWithoutAuthTests(TestCase):
|
||||||
response = self.client.get('/')
|
response = self.client.get('/')
|
||||||
content = response.content.decode()
|
content = response.content.decode()
|
||||||
assert '<li class="dropdown">' not in content
|
assert '<li class="dropdown">' not in content
|
||||||
|
|
||||||
|
|
||||||
|
class BasicModelSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = BasicModel
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceViewSet(ModelViewSet):
|
||||||
|
serializer_class = BasicModelSerializer
|
||||||
|
queryset = BasicModel.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
router = SimpleRouter()
|
||||||
|
router.register(r'resources', ResourceViewSet)
|
||||||
|
router.register(r'resources-2', ResourceViewSet)
|
||||||
|
urlpatterns = []
|
||||||
|
urlpatterns += router.urls
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(ROOT_URLCONF='tests.browsable_api.test_browsable_api')
|
||||||
|
class SeleniumTests(StaticLiveServerTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
cls.selenium = WebDriver()
|
||||||
|
cls.selenium.implicitly_wait(10)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
cls.selenium.quit()
|
||||||
|
super().tearDownClass()
|
||||||
|
|
||||||
|
def test_post_raw_data(self):
|
||||||
|
self.selenium.get('%s%s' % (self.live_server_url, '/resources'))
|
||||||
|
raw_tab = self.selenium.find_element(By.NAME, "raw-tab")
|
||||||
|
raw_tab.click()
|
||||||
|
|
||||||
|
# Raw data textarea is pre-populated with empty value.
|
||||||
|
text_input = self.selenium.find_element(By.ID, "id__content")
|
||||||
|
self.assertEqual(json.loads(text_input.text), {'text': ''})
|
||||||
|
|
||||||
|
# Do submit and the data will be presisted then.
|
||||||
|
text_input.clear()
|
||||||
|
json_data = json.dumps({"text": "text description"}, indent=4)
|
||||||
|
text_input.send_keys(json_data)
|
||||||
|
post_button = self.selenium.find_element(By.CSS_SELECTOR, '#post-generic-content-form div.form-actions button')
|
||||||
|
post_button.click()
|
||||||
|
text_input = self.selenium.find_element(By.ID, "id__content")
|
||||||
|
self.assertEqual(json.loads(text_input.text), {'text': 'text description'})
|
||||||
|
self.assertEqual(BasicModel.objects.last().text, 'text description')
|
||||||
|
|
||||||
|
# Moving to another resource view, the raw data will be clean.
|
||||||
|
self.selenium.get('%s%s' % (self.live_server_url, '/resources-2'))
|
||||||
|
text_input = self.selenium.find_element(By.ID, "id__content")
|
||||||
|
self.assertEqual(json.loads(text_input.text), {'text': ''})
|
||||||
|
|
||||||
|
# Do a second submit from the second view.
|
||||||
|
text_input.clear()
|
||||||
|
json_data = json.dumps({"text": "text description 2"}, indent=4)
|
||||||
|
text_input.send_keys(json_data)
|
||||||
|
post_button = self.selenium.find_element(By.CSS_SELECTOR, '#post-generic-content-form div.form-actions button')
|
||||||
|
post_button.click()
|
||||||
|
text_input = self.selenium.find_element(By.ID, "id__content")
|
||||||
|
self.assertEqual(json.loads(text_input.text), {'text': 'text description 2'})
|
||||||
|
self.assertEqual(BasicModel.objects.last().text, 'text description 2')
|
||||||
|
|
||||||
|
# Do a third submit, from the same view, with the previous data
|
||||||
|
# (which was pre-populated).
|
||||||
|
post_button = self.selenium.find_element(By.CSS_SELECTOR, '#post-generic-content-form div.form-actions button')
|
||||||
|
post_button.click()
|
||||||
|
self.assertEqual(BasicModel.objects.count(), 3)
|
||||||
|
self.assertEqual(BasicModel.objects.last().text, 'text description 2')
|
||||||
|
|
||||||
|
# Only two keys were stored.
|
||||||
|
session_storage_data = self.selenium.execute_script(
|
||||||
|
'return JSON.parse(sessionStorage.getItem("rawDataSubmitted"))'
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['/resources-2/', '/resources/'],
|
||||||
|
list(session_storage_data.keys())
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['{\n "text": "text description 2"\n}', '{\n "text": "text description"\n}'],
|
||||||
|
list(session_storage_data.values())
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user