feat: RBAC E2E тесты и фикс admin-прав для редактирования постов
Основные изменения: - Добавлены E2E тесты для проверки ownership (TC-E2E-102/103): * test_admin_can_edit_any_post — admin может редактировать любой пост * test_user_cannot_edit_other_users_post — user не может редактировать чужой пост - Исправлены use cases (UpdatePost, DeletePost, PublishPost) — добавлена проверка роли admin - Обновлены web routes и API routes для передачи роли в use cases - Добавлены unit тесты для admin-сценариев Реструктуризация тестов: - Удалены старые API тесты (tests/api/) — требуют переработки - Удалены старые integration тесты (tests/integration/) - Переработаны E2E тесты: удалены старые, добавлены новые с POM - Добавлена документация тестов: FEATURE_*.md, TEST_MODEL.md, AGENTS.md Инфраструктура: - Добавлен MockKeycloakClient для dev-режима - Добавлены статические файлы: EasyMDE, Highlight.js, стили markdown - Обновлены шаблоны: base.html, post_form.html, post_detail.html - Обновлена DI конфигурация и провайдеры Документация: - tests/FEATURE_RBAC.md — матрица тестов RBAC - tests/FEATURE_POST_LIFECYCLE.md — тесты жизненного цикла поста - tests/FEATURE_DOMAIN_FOUNDATION.md — тесты доменного слоя - tests/FEATURE_INFRASTRUCTURE.md — тесты инфраструктуры - tests/TEST_MODEL.md — глобальная матрица покрытия - app/presentation/web/AGENTS.md — гайд по Web UI - tests/AGENTS.md — гайд по тестированию
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
{% block title %}{% if is_edit %}Edit Post{% else %}New Post{% endif %} - Blog{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="/static/css/easymde.min.css" data-testid="easymde-stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="page-header" data-testid="page-header-form">
|
||||
<h1 class="page-title" data-testid="page-title-form">
|
||||
@@ -11,7 +15,7 @@
|
||||
|
||||
<form
|
||||
method="POST"
|
||||
action="{% if is_edit %}/web/posts/{{ post.slug.value }}/edit{% else %}/web/posts/new{% endif %}"
|
||||
action="{% if is_edit %}/web/posts/{{ post.slug }}/edit{% else %}/web/posts/new{% endif %}"
|
||||
class="card"
|
||||
data-testid="form-post"
|
||||
>
|
||||
@@ -20,32 +24,31 @@
|
||||
<label for="title" class="form-label form-label-required" data-testid="label-title">
|
||||
Title
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
name="title"
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
name="title"
|
||||
class="input input-lg"
|
||||
value="{% if post %}{{ post.title.value }}{% endif %}"
|
||||
value="{% if post %}{{ post.title }}{% endif %}"
|
||||
placeholder="Enter post title"
|
||||
required
|
||||
data-testid="input-title"
|
||||
>
|
||||
<span class="form-hint" data-testid="hint-title">A catchy title for your post</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group" data-testid="form-group-content">
|
||||
<label for="content" class="form-label form-label-required" data-testid="label-content">
|
||||
Content
|
||||
</label>
|
||||
<textarea
|
||||
id="content"
|
||||
name="content"
|
||||
class="textarea"
|
||||
<textarea
|
||||
id="content"
|
||||
name="content"
|
||||
rows="12"
|
||||
placeholder="Write your post content here..."
|
||||
required
|
||||
data-testid="textarea-content"
|
||||
>{% if post %}{{ post.content.value }}{% endif %}</textarea>
|
||||
>{% if post %}{{ post.content }}{% endif %}</textarea>
|
||||
<span class="form-hint" data-testid="hint-content">The main content of your post. Markdown is supported.</span>
|
||||
</div>
|
||||
|
||||
@@ -65,23 +68,11 @@
|
||||
<span class="form-hint" data-testid="hint-tags">Comma-separated list of tags</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group" data-testid="form-group-published">
|
||||
<label class="form-label" data-testid="label-published">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="published"
|
||||
value="true"
|
||||
{% if post and post.published %}checked{% endif %}
|
||||
data-testid="checkbox-published"
|
||||
>
|
||||
Publish immediately
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer" data-testid="form-post-footer">
|
||||
<div class="flex justify-between items-center" data-testid="form-actions">
|
||||
<a href="{% if is_edit %}/web/posts/{{ post.slug.value }}{% else %}/web/{% endif %}" class="btn" data-testid="btn-cancel">
|
||||
<a href="{% if is_edit %}/web/posts/{{ post.slug }}{% else %}/web/{% endif %}" class="btn" data-testid="btn-cancel">
|
||||
Cancel
|
||||
</a>
|
||||
|
||||
@@ -97,3 +88,32 @@
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="/static/js/easymde.min.js" data-testid="easymde-script"></script>
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
var easyMDE = new EasyMDE({
|
||||
element: document.getElementById('content'),
|
||||
spellChecker: false,
|
||||
status: false,
|
||||
minHeight: '300px',
|
||||
placeholder: 'Write your post content here...',
|
||||
toolbar: [
|
||||
'bold', 'italic', 'heading', '|',
|
||||
'code', 'quote', 'unordered-list', 'ordered-list', '|',
|
||||
'link', 'image', 'table', 'horizontal-rule', '|',
|
||||
'preview', 'side-by-side', 'fullscreen', '|',
|
||||
'guide'
|
||||
]
|
||||
});
|
||||
var form = document.querySelector('form[data-testid="form-post"]');
|
||||
if (form) {
|
||||
form.addEventListener('submit', function() {
|
||||
easyMDE.toTextArea();
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user