Fix: step 2 -> step 2b/3 workflow
Some checks failed
Build & Push Docker / build (push) Has been cancelled
Some checks failed
Build & Push Docker / build (push) Has been cancelled
Problem:
- Když uživatel importoval Excel a klikl 'Upravit v inline editoru' nebo 'Generovat',
dostal chybu 'Neplatný krok nebo chybějící data'
- step 2b vyžadoval file_item, ale formulář posílal file_content_base64
Řešení:
- Upravena podmínka pro step=2b aby akceptovala i file_content_base64
- Přidány 2 nové testy:
* test_excel_import_to_step2_workflow - testuje import -> step 2 -> step 3 (generate)
* test_excel_import_to_inline_editor_workflow - testuje import -> step 2 -> step 2b (inline editor)
Testy: 18/18 unit testů prošlo ✅
This commit is contained in:
@@ -583,17 +583,28 @@ button:hover { background: #0056b3; }
|
|||||||
logger.error(f"Unexpected error: {str(e)}")
|
logger.error(f"Unexpected error: {str(e)}")
|
||||||
render_error(f"Neočekávaná chyba: {str(e)}")
|
render_error(f"Neočekávaná chyba: {str(e)}")
|
||||||
|
|
||||||
elif step == '2b' and file_item is not None and file_item.filename:
|
elif step == '2b':
|
||||||
"""Load Excel data into inline editor for editing."""
|
"""Load Excel data into inline editor for editing."""
|
||||||
try:
|
try:
|
||||||
file_content = file_item.file.read()
|
# Get file content from either file upload or base64
|
||||||
file_size = len(file_content)
|
file_content = None
|
||||||
|
if file_item is not None and file_item.filename:
|
||||||
|
file_content = file_item.file.read()
|
||||||
|
else:
|
||||||
|
file_content_base64 = form.getvalue('file_content_base64', '')
|
||||||
|
if file_content_base64:
|
||||||
|
file_content = base64.b64decode(file_content_base64)
|
||||||
|
|
||||||
# Validate inputs
|
if not file_content:
|
||||||
validate_inputs(title, detail, file_size)
|
render_error("Chyba: Soubor nebyl nalezen.")
|
||||||
|
else:
|
||||||
# Read Excel
|
file_size = len(file_content)
|
||||||
data, error_rows = read_excel(file_content, show_debug)
|
|
||||||
|
# Validate inputs
|
||||||
|
validate_inputs(title, detail, file_size)
|
||||||
|
|
||||||
|
# Read Excel
|
||||||
|
data, error_rows = read_excel(file_content, show_debug)
|
||||||
|
|
||||||
if data.empty:
|
if data.empty:
|
||||||
render_error("Načtená data jsou prázdná nebo obsahují neplatné hodnoty. Zkontrolujte vstupní soubor.")
|
render_error("Načtená data jsou prázdná nebo obsahují neplatné hodnoty. Zkontrolujte vstupní soubor.")
|
||||||
|
|||||||
@@ -249,3 +249,113 @@ def test_inline_workflow_integration():
|
|||||||
ws = wb.active
|
ws = wb.active
|
||||||
assert ws['A1'].value == "Integration Test Event"
|
assert ws['A1'].value == "Integration Test Event"
|
||||||
assert ws['A2'].value == "Testing inline workflow"
|
assert ws['A2'].value == "Testing inline workflow"
|
||||||
|
|
||||||
|
|
||||||
|
def test_excel_import_to_step2_workflow():
|
||||||
|
"""Test workflow: Excel import -> step 2 (type definition) -> step 3 (generate).
|
||||||
|
This simulates the user uploading Excel, then filling type definitions.
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# Step 1: Create Excel file
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'Datum': [pd.Timestamp('2025-11-13').date()],
|
||||||
|
'Zacatek': ['09:00'],
|
||||||
|
'Konec': ['10:00'],
|
||||||
|
'Program': ['Opening Keynote'],
|
||||||
|
'Typ': ['KEYNOTE'],
|
||||||
|
'Garant': ['John Smith'],
|
||||||
|
'Poznamka': ['Welcome speech']
|
||||||
|
})
|
||||||
|
|
||||||
|
file_content = make_excel_bytes(df)
|
||||||
|
|
||||||
|
# Step 2: Read Excel (simulating step=2 processing)
|
||||||
|
valid_data, errors = read_excel(file_content)
|
||||||
|
assert len(errors) == 0
|
||||||
|
assert len(valid_data) == 1
|
||||||
|
|
||||||
|
# Extract types
|
||||||
|
program_types = sorted([str(t).strip() for t in valid_data["Typ"].dropna().unique()])
|
||||||
|
assert program_types == ['KEYNOTE']
|
||||||
|
|
||||||
|
# Step 3: User fills type definitions (simulating form submission in step=2)
|
||||||
|
# This would be base64 encoded in the hidden field
|
||||||
|
file_content_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
|
||||||
|
form_data = {
|
||||||
|
'title': 'Test Event',
|
||||||
|
'detail': 'Test Detail',
|
||||||
|
'file_content_base64': file_content_base64,
|
||||||
|
'type_code_0': 'KEYNOTE',
|
||||||
|
'desc_0': 'Main keynote presentation',
|
||||||
|
'color_0': '#FF0000',
|
||||||
|
'step': '3'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse types (simulating step=3 processing)
|
||||||
|
descriptions, colors = get_program_types(form_data)
|
||||||
|
|
||||||
|
assert descriptions['KEYNOTE'] == 'Main keynote presentation'
|
||||||
|
assert colors['KEYNOTE'] == 'FFFF0000'
|
||||||
|
|
||||||
|
# Step 4: Generate timetable
|
||||||
|
# Re-read Excel from base64
|
||||||
|
file_content_decoded = base64.b64decode(form_data['file_content_base64'])
|
||||||
|
data, _ = read_excel(file_content_decoded)
|
||||||
|
|
||||||
|
wb = create_timetable(
|
||||||
|
data,
|
||||||
|
title=form_data['title'],
|
||||||
|
detail=form_data['detail'],
|
||||||
|
program_descriptions=descriptions,
|
||||||
|
program_colors=colors
|
||||||
|
)
|
||||||
|
|
||||||
|
assert wb is not None
|
||||||
|
ws = wb.active
|
||||||
|
assert ws['A1'].value == 'Test Event'
|
||||||
|
assert ws['A2'].value == 'Test Detail'
|
||||||
|
|
||||||
|
|
||||||
|
def test_excel_import_to_inline_editor_workflow():
|
||||||
|
"""Test workflow: Excel import -> step 2 -> step 2b (inline editor).
|
||||||
|
This simulates clicking 'Upravit v inline editoru' button.
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# Create Excel file
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'Datum': [pd.Timestamp('2025-11-13').date(), pd.Timestamp('2025-11-14').date()],
|
||||||
|
'Zacatek': ['09:00', '14:00'],
|
||||||
|
'Konec': ['10:00', '15:30'],
|
||||||
|
'Program': ['Morning Session', 'Afternoon Workshop'],
|
||||||
|
'Typ': ['KEYNOTE', 'WORKSHOP'],
|
||||||
|
'Garant': ['Alice', 'Bob'],
|
||||||
|
'Poznamka': ['', 'Hands-on']
|
||||||
|
})
|
||||||
|
|
||||||
|
file_content = make_excel_bytes(df)
|
||||||
|
|
||||||
|
# Step 2: Read Excel
|
||||||
|
valid_data, errors = read_excel(file_content)
|
||||||
|
assert len(errors) == 0
|
||||||
|
assert len(valid_data) == 2
|
||||||
|
|
||||||
|
# Step 2b: User clicks "Upravit v inline editoru"
|
||||||
|
# The form would pass file_content_base64 to step=2b
|
||||||
|
file_content_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
|
||||||
|
# Simulate step 2b: decode and re-read Excel
|
||||||
|
file_content_decoded = base64.b64decode(file_content_base64)
|
||||||
|
data_in_editor, _ = read_excel(file_content_decoded)
|
||||||
|
|
||||||
|
# Verify data loaded correctly
|
||||||
|
assert len(data_in_editor) == 2
|
||||||
|
assert data_in_editor.iloc[0]['Program'] == 'Morning Session'
|
||||||
|
assert data_in_editor.iloc[1]['Program'] == 'Afternoon Workshop'
|
||||||
|
|
||||||
|
# Extract types for editor
|
||||||
|
program_types = sorted([str(t).strip() for t in data_in_editor["Typ"].dropna().unique()])
|
||||||
|
assert set(program_types) == {'KEYNOTE', 'WORKSHOP'}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user