WIP: 2021 02 24 dockerize (#18)
* Use cache for most fields and admin form for m2m files * MR comments/clean up * Cache should obey exclude and fields * Some more tests and docs * Only use cache for image files * Even more tests and handle save as new * fix test * More tests * minor refactor * Improve test coverage * Adding tests for fieldsets * Added cache timeout * Added another test for an edge case * Fix issue with ManagementForm tampered with * Update cache to only set when form is_multipart * Even more testing changes * Dockerize * Setting up tests in docker * Update github actions * Got first integration test to work * Refactor a bit * Fix github action yml * Use docker-compose up -d in github actions * combine coveralls * Updated readme * Clean up code * Remove dup code from rebase Co-authored-by: Thu Trang Pham <thu@joinmodernhealth.com>main
parent
06d3e1a208
commit
4f50c63f7b
|
|
@ -0,0 +1,36 @@
|
|||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
build/
|
||||
dist/
|
||||
sdist/
|
||||
.eggs/
|
||||
*.egg-info/
|
||||
.DS_Store
|
||||
|
||||
# Editor settings
|
||||
.vscode/
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
*.db
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# pycharm
|
||||
.idea/
|
||||
|
||||
tmp/
|
||||
|
|
@ -49,8 +49,24 @@ jobs:
|
|||
parallel: true
|
||||
flag-name: Unit Test
|
||||
|
||||
integration-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build Docker
|
||||
run: docker-compose build
|
||||
- name: Start Docker
|
||||
run: docker-compose up -d
|
||||
- name: Integration Test
|
||||
run: docker-compose run web make test-all
|
||||
- name: Coveralls
|
||||
uses: AndreMiras/coveralls-python-action@develop
|
||||
with:
|
||||
parallel: true
|
||||
flag-name: Integration Test
|
||||
|
||||
coveralls:
|
||||
needs: test
|
||||
needs: [test, integration-test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Coveralls Finished
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
django-admin-confirm-3.8
|
||||
django-admin-confirm-3.8.0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
FROM python:3
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV USE_DOCKER=true
|
||||
WORKDIR /code
|
||||
COPY requirements.txt /code/
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . /code/
|
||||
7
Makefile
7
Makefile
|
|
@ -2,9 +2,16 @@ run:
|
|||
./tests/manage.py runserver
|
||||
|
||||
test:
|
||||
coverage run --source admin_confirm --branch -m pytest --ignore=admin_confirm/tests/integration
|
||||
coverage report -m
|
||||
|
||||
test-all:
|
||||
coverage run --source admin_confirm --branch -m pytest
|
||||
coverage report -m
|
||||
|
||||
t:
|
||||
python -m pytest --last-failed -x
|
||||
|
||||
check-readme:
|
||||
python -m readme_renderer README.md -o /tmp/README.html
|
||||
|
||||
|
|
|
|||
68
README.md
68
README.md
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
AdminConfirmMixin is a mixin for ModelAdmin to add confirmations to change, add and actions.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
It can be configured to add a confirmation page on ModelAdmin upon:
|
||||
|
||||
|
|
@ -139,18 +139,21 @@ Your appreciation is also very welcome :) Feel free to:
|
|||
|
||||
### Local Development Setup
|
||||
|
||||
**Local:**
|
||||
_You can skip this and just use docker if you want_
|
||||
|
||||
Install pyenv
|
||||
Install python 3.8
|
||||
pyenv install 3.8.0
|
||||
|
||||
Create virtualenv via pyenv
|
||||
Create **virtualenv** via pyenv
|
||||
|
||||
```
|
||||
pyenv vituralenv 3.8 django-admin-confirm-3.8
|
||||
pyenv vituralenv 3.8.0 django-admin-confirm-3.8.0
|
||||
```
|
||||
|
||||
Now your terminal should have `(django-admin-confirm-3.8)` prefix, because `.python-version` should have auto switch your virtual env
|
||||
Now your terminal should have `(django-admin-confirm-3.8.0)` prefix, because `.python-version` should have auto switch your virtual env
|
||||
|
||||
Run migrations and create a superuser and run the server
|
||||
Run **migrations** and create a superuser and run the server
|
||||
|
||||
```
|
||||
./tests/manage.py migrate
|
||||
|
|
@ -160,19 +163,54 @@ Run migrations and create a superuser and run the server
|
|||
|
||||
You should be able to see the test app at `localhost:8000/admin`
|
||||
|
||||
Running tests:
|
||||
**Running tests:**
|
||||
|
||||
```
|
||||
make test
|
||||
```sh
|
||||
make test # Runs unit tests with coverage locally without integration tests
|
||||
make test-all # Runs unit tests + integration tests, requires extra setup to run locally
|
||||
```
|
||||
|
||||
Testing new changes on test project:
|
||||
Use `python -m pytest` if you want to pass in arguments
|
||||
|
||||
`make t` is a short cut to run without coverage, last-failed, and fail fast
|
||||
|
||||
Testing local changes on test project:
|
||||
|
||||
```
|
||||
pip install -e .
|
||||
make run
|
||||
```
|
||||
|
||||
**Docker:**
|
||||
|
||||
Instead of local set-up, you can also use docker.
|
||||
|
||||
Install docker-compose (or Docker Desktop which installs this for you)
|
||||
|
||||
```
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
You should now be able to see the app running on `localhost:8000`
|
||||
|
||||
If you haven't already done migrations and created a superuser, you'll want to do it here
|
||||
|
||||
```
|
||||
docker-compose exec web tests/manage.py migrate
|
||||
docker-compose exec web tests/manage.py createsuperuser
|
||||
```
|
||||
|
||||
Running tests in docker:
|
||||
|
||||
```
|
||||
docker-compose exec -T web make test-all
|
||||
```
|
||||
|
||||
The integration tests are set up within docker. I recommend running the integration tests only in docker.
|
||||
|
||||
Docker is also set to mirror local folder so that you can edit code/tests and don't have to rebuild to run new code/tests.
|
||||
|
||||
### Release process
|
||||
|
||||
Honestly this part is just for my reference. But who knows :) maybe we'll have another maintainer in the future.
|
||||
|
|
@ -180,7 +218,7 @@ Honestly this part is just for my reference. But who knows :) maybe we'll have a
|
|||
Run tests, check coverage, check readme
|
||||
|
||||
```
|
||||
make test
|
||||
docker-compose exec -T web make test-all
|
||||
make check-readme
|
||||
```
|
||||
|
||||
|
|
@ -188,7 +226,7 @@ Update version in `setup.py`
|
|||
|
||||
```
|
||||
make package
|
||||
make upload-testpypi
|
||||
make upload-testpypi VERSION=<VERSION>
|
||||
```
|
||||
|
||||
Install new version locally
|
||||
|
|
@ -196,7 +234,7 @@ First you have to uninstall if you used `pip install -e` earlier
|
|||
|
||||
```
|
||||
pip uninstall django_admin_confirm
|
||||
make install-testpypi
|
||||
make install-testpypi VERSION=<VERSION>
|
||||
```
|
||||
|
||||
Update version in `requirements.txt`
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
|
||||
{% if form.is_multipart %}<input type="hidden" name=CONFIRMATION_RECEIVED value="True">{% endif %}
|
||||
{% if form.is_multipart %}<input type="hidden" name="_confirmation_received" value="True">{% endif %}
|
||||
<div class="submit-row">
|
||||
<input type="submit" value="{% trans 'Yes, I’m sure' %}" name="{{ submit_name }}">
|
||||
<p class="deletelink-box">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ from django.core.cache import cache
|
|||
from django.test import TestCase, RequestFactory
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class AdminConfirmTestCase(TestCase):
|
||||
"""
|
||||
Helper TestCase class and common associated assertions
|
||||
|
|
@ -43,7 +42,7 @@ class AdminConfirmTestCase(TestCase):
|
|||
self.assertNotIn("_confirm_change", rendered_content)
|
||||
|
||||
confirmation_received_html = (
|
||||
'<input type="hidden" name=CONFIRMATION_RECEIVED value="True">'
|
||||
'<input type="hidden" name="_confirmation_received" value="True">'
|
||||
)
|
||||
|
||||
if multipart_form:
|
||||
|
|
@ -56,3 +55,31 @@ class AdminConfirmTestCase(TestCase):
|
|||
for k, v in fields.items():
|
||||
self.assertIn(f'name="{k}"', rendered_content)
|
||||
self.assertIn(f'value="{v}"', rendered_content)
|
||||
|
||||
def _assertFormsetsFormHtml(self, rendered_content, inlines):
|
||||
for inline in inlines:
|
||||
for field in inline.fields:
|
||||
self.assertIn("apple", rendered_content)
|
||||
|
||||
|
||||
|
||||
import socket
|
||||
from django.test import LiveServerTestCase
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
|
||||
|
||||
class AdminConfirmIntegrationTestCase(LiveServerTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.host = socket.gethostbyname(socket.gethostname())
|
||||
cls.selenium = webdriver.Remote(
|
||||
command_executor="http://selenium:4444/wd/hub",
|
||||
desired_capabilities=DesiredCapabilities.FIREFOX,
|
||||
)
|
||||
super().setUpClass()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.selenium.quit()
|
||||
super().tearDownClass()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
from admin_confirm.tests.helpers import AdminConfirmIntegrationTestCase
|
||||
|
||||
|
||||
class SmokeTest(AdminConfirmIntegrationTestCase):
|
||||
def test_load_admin(self):
|
||||
self.selenium.get(self.live_server_url+'/admin/')
|
||||
self.assertIn('Django', self.selenium.title)
|
||||
|
|
@ -6,7 +6,7 @@ from tests.market.admin import ShoppingMallAdmin
|
|||
from tests.market.models import GeneralManager, ShoppingMall, Town
|
||||
from tests.factories import ShopFactory
|
||||
|
||||
from admin_confirm.constants import CACHE_KEYS, CONFIRMATION_RECEIVED
|
||||
from admin_confirm.constants import CACHE_KEYS
|
||||
|
||||
|
||||
@mock.patch.object(ShoppingMallAdmin, "inlines", [])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
version: "3.9"
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
command: python tests/manage.py runserver 0.0.0.0:8000
|
||||
volumes:
|
||||
- .:/code
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
- selenium
|
||||
selenium:
|
||||
# image: selenium/standalone-firefox
|
||||
image: selenium/standalone-firefox-debug:latest
|
||||
ports:
|
||||
- "4444:4444" # Selenium
|
||||
- "5900:5900" # VNC
|
||||
|
|
@ -17,12 +17,3 @@ class ItemAdmin(AdminConfirmMixin, ModelAdmin):
|
|||
def image_preview(self, obj):
|
||||
if obj.image:
|
||||
return mark_safe('<img src="{obj.image.url}" />')
|
||||
|
||||
# def one(self, obj):
|
||||
# return "Read Only"
|
||||
|
||||
# def two(self, obj):
|
||||
# return "Read Only"
|
||||
|
||||
# def three(self, obj):
|
||||
# return "Read Only"
|
||||
|
|
|
|||
|
|
@ -24,8 +24,13 @@ SECRET_KEY = "=yddl-40388w3e2hl$e8)revce=n67_idi8pfejtn3!+2%!_qt"
|
|||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
|
||||
USE_DCOKER = os.environ.get("USE_DOCKER", '').lower() == "true"
|
||||
|
||||
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
|
||||
if USE_DCOKER:
|
||||
import socket
|
||||
|
||||
ALLOWED_HOSTS = [socket.gethostbyname(socket.gethostname())]
|
||||
|
||||
# Application definition
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue