import pytest from flexoentity import FlexOID, FlexoEntity, EntityState # ────────────────────────────────────────────────────────────────────────────── # Tests adapted to use real SingleChoiceQuestion fixture instead of DummyEntity # ────────────────────────────────────────────────────────────────────────────── def test_initial_state(sample_question): q = sample_question assert q.state == EntityState.DRAFT assert q.flexo_id.version == 1 assert FlexoEntity.verify_integrity(q) def test_approval_does_not_bump_version(sample_question): q = sample_question q.approve() assert q.state == EntityState.APPROVED assert q.flexo_id.version == 1 def test_signing_does_not_bump_version(sample_question): q = sample_question q.approve() before = q.flexo_id q.sign() after = q.flexo_id # state changed assert q.state == EntityState.APPROVED_AND_SIGNED # version unchanged assert before.version == after.version # only suffix letter differs assert before.prefix == after.prefix assert before.state_code == "A" assert after.state_code == "S" def test_publish_does_not_bump_version(sample_question): q = sample_question q.approve() q.sign() v_before = q.flexo_id.version q.publish() assert q.state == EntityState.PUBLISHED assert q.flexo_id.version == v_before def test_modify_content_changes_fingerprint(sample_question): q = sample_question q.text += "Rephrased content" # simulate text change changed = q._update_fingerprint() assert changed def test_no_version_bump_on_draft_edits(sample_question): q = sample_question q.text = "Minor draft edit" q._update_fingerprint() assert q.flexo_id.version == 1 def test_version_bump_after_edit_and_sign(sample_question): q = sample_question q.approve() v1 = str(q.flexo_id) q.text = "Changed content" q.sign() assert str(q.flexo_id) != v1 def test_integrity_check_passes_and_fails(sample_question): q = sample_question q.approve() assert FlexoEntity.verify_integrity(q) # simulate tampering q.text = "Tampered text" assert not FlexoEntity.verify_integrity(q) def test_obsolete_state(sample_question): q = sample_question q.approve() q.sign() q.publish() q.obsolete() assert q.state == EntityState.OBSOLETE def test_clone_new_base_resets_lineage(sample_question): q = sample_question q.approve() q.sign() q.publish() q.obsolete() old_id = str(q.flexo_id) q.clone_new_base() assert str(q.flexo_id) != old_id assert q.state == EntityState.DRAFT assert q.flexo_id.version == 1 def test_clone_new_base_sets_origin(sample_question): q = sample_question q.approve() q.sign() q.publish() q.obsolete() old_id = str(q.flexo_id) q.clone_new_base() assert q.origin == old_id assert q.state == EntityState.DRAFT assert q.flexo_id.version == 1 assert q.flexo_id != old_id def test_mass_version_increments_until_obsolete(sample_question): q = sample_question q.approve() for _ in range(FlexOID.MAX_VERSION - 1): q.bump_version() # Next one must raise with pytest.raises(RuntimeError, match="mark obsolete"): q.bump_version()