source: flexoentity/tests/conftest.py@ a475496

Last change on this file since a475496 was b24d72e, checked in by Enrico Schwass <ennoausberlin@…>, 8 weeks ago

move DomainManager to FlexoGrader

  • Property mode set to 100644
File size: 3.0 KB
RevLine 
[8aa20c7]1# tests/stubs/single_choice_question.py
[8a238e2]2import pytest
[8aa20c7]3from datetime import datetime
4from dataclasses import dataclass, field
5from typing import List
[b24d72e]6from flexoentity import FlexOID, FlexoEntity, EntityType, EntityState, Domain
[8a238e2]7
[8aa20c7]8@pytest.fixture
9def fixed_datetime(monkeypatch):
10 class FixedDate(datetime):
11 @classmethod
12 def now(cls, tz=None):
13 return datetime(2025, 11, 1, tzinfo=tz)
14 monkeypatch.setattr("flexoentity.id_factory.datetime", FixedDate)
15 return FixedDate
[02d288d]16
[8aa20c7]17@dataclass
18class AnswerOption:
19 id: str
20 text: str
21 points: float = 0.0
[02d288d]22
[8aa20c7]23 def to_dict(self):
24 return {"id": self.id, "text": self.text, "points": self.points}
[8a238e2]25
[8aa20c7]26 @classmethod
27 def from_dict(cls, data):
28 return cls(
29 id=data.get("id", ""),
30 text=data.get("text", ""),
31 points=data.get("points", 0.0)
32 )
[02d288d]33
34
[8aa20c7]35@dataclass
36class SingleChoiceQuestion(FlexoEntity):
37 """A minimal stub to test FlexoEntity integration."""
[5c72356]38 ENTITY_TYPE = EntityType.ITEM
39
[8aa20c7]40 text: str = ""
41 options: List[AnswerOption] = field(default_factory=list)
[02d288d]42
[5c72356]43 def __post_init__(self):
44 # If no FlexOID yet, generate a draft ID now.
45 if not getattr(self, "flexo_id", None):
46 self.flexo_id = FlexOID.safe_generate(
[9592936]47 domain_id=self.domain_id,
[269fdc2]48 entity_type=SingleChoiceQuestion.ENTITY_TYPE.value, # 'I'
[9592936]49 state=EntityState.DRAFT.value, # 'D'
[5c72356]50 text=self.text_seed or self.text,
51 version=1,
52 )
[02d288d]53
[8aa20c7]54 @classmethod
55 def default(cls):
[269fdc2]56 return cls()
[02d288d]57
[8aa20c7]58 def to_dict(self):
59 base = super().to_dict()
60 base.update({
61 "text": self.text,
62 "options": [opt.to_dict() for opt in self.options],
63 })
64 return base
65
66 @property
67 def text_seed(self) -> str:
68 """Include answer options (and points) for deterministic ID generation."""
69
70 joined = "|".join(
71 f"{opt.text.strip()}:{opt.points}"
72 for opt in sorted(self.options, key=lambda o: o.text.strip().lower())
73 )
74 return f"{self.text}{joined}"
75
76 @classmethod
77 def from_dict(cls, data):
[269fdc2]78 obj = cls(text=data.get("text", ""),
[8aa20c7]79 options=[AnswerOption.from_dict(o) for o in data.get("options", [])],
80 )
81 # restore FlexoEntity core fields
82 if "flexo_id" in data:
[fd1913f]83 obj.flexo_id = FlexOID.to_dict(data["flexo_id"])
[8aa20c7]84 return obj
85
86@pytest.fixture
[6ad031b]87def sample_domain():
88 domain_id = "PY_ARITHM"
[9592936]89 return Domain.with_domain_id(domain_id=domain_id,
90 fullname="PYTHON_ARITHMETIC",
91 description="ALL ABOUT ARITHMETIC IN PYTHON")
[3d16c35]92
[524040a]93@pytest.fixture
[6ad031b]94def sample_question(sample_domain):
[9592936]95 q = SingleChoiceQuestion.with_domain_id(domain_id=sample_domain.domain_id,
96 text="What is 2 + 2?",
97 options=[])
[5c72356]98 q._update_fingerprint()
99 return q
Note: See TracBrowser for help on using the repository browser.