diff --git a/amt/api/lifecycles.py b/amt/api/lifecycles.py new file mode 100644 index 00000000..cfe4a5b5 --- /dev/null +++ b/amt/api/lifecycles.py @@ -0,0 +1,54 @@ +import logging +from enum import Enum + +from fastapi import Request + +from amt.core.internationalization import get_current_translation +from amt.schema.lifecycle import Lifecycle + +logger = logging.getLogger(__name__) + + +class Lifecycles(Enum): + ORGANIZATIONAL_RESPONSIBILITIES = "ORGANIZATIONAL_RESPONSIBILITIES" + PROBLEM_ANALYSIS = "PROBLEM_ANALYSIS" + DESIGN = "DESIGN" + DATA_EXPLORATION_AND_PREPARATION = "DATA_EXPLORATION_AND_PREPARATION" + DEVELOPMENT = "DEVELOPMENT" + VERIFICATION_AND_VALIDATION = "VERIFICATION_AND_VALIDATION" + IMPLEMENTATION = "IMPLEMENTATION" + MONITORING_AND_MANAGEMENT = "MONITORING_AND_MANAGEMENT" + PHASING_OUT = "PHASING_OUT" + + +def get_lifecycle(key: Lifecycles | None, request: Request) -> Lifecycle | None: + """ + Given the key and translation, returns the translated text. + :param key: the key + :param request: request to get the current language + :return: a Lifecycle model with the correct translation + """ + + if key is None: + return None + + translations = get_current_translation(request) + _ = translations.gettext + # translations are determined at runtime, which is why we use the dictionary below + keys = { + Lifecycles.ORGANIZATIONAL_RESPONSIBILITIES: _("Organizational Responsibilities"), + Lifecycles.PROBLEM_ANALYSIS: _("Problem Analysis"), + Lifecycles.DESIGN: _("Design"), + Lifecycles.DATA_EXPLORATION_AND_PREPARATION: _("Data Exploration and Preparation"), + Lifecycles.DEVELOPMENT: _("Development"), + Lifecycles.VERIFICATION_AND_VALIDATION: _("Verification and Validation"), + Lifecycles.IMPLEMENTATION: _("Implementation"), + Lifecycles.MONITORING_AND_MANAGEMENT: _("Monitoring and Management"), + Lifecycles.PHASING_OUT: _("Phasing Out"), + } + return Lifecycle(id=key.value, name=keys[key]) + + +def get_lifecycles(request: Request) -> list[Lifecycle | None]: + lifecycles: list[Lifecycle | None] = [get_lifecycle(lifecycle, request) for lifecycle in Lifecycles] + return lifecycles diff --git a/amt/api/routes/project.py b/amt/api/routes/project.py index cf5e8abf..fd7d814b 100644 --- a/amt/api/routes/project.py +++ b/amt/api/routes/project.py @@ -6,6 +6,7 @@ from fastapi.responses import HTMLResponse from amt.api.deps import templates +from amt.api.lifecycles import get_lifecycle from amt.api.navigation import ( BaseNavigationItem, Navigation, @@ -161,6 +162,7 @@ async def get_project_details( tab_items = get_project_details_tabs(request) context = { + "lifecycle": get_lifecycle(project.lifecycle, request), "system_card": system_card_data, "instrument_state": instrument_state, "project": project, diff --git a/amt/api/routes/projects.py b/amt/api/routes/projects.py index 7db6f2da..990f9640 100644 --- a/amt/api/routes/projects.py +++ b/amt/api/routes/projects.py @@ -6,6 +6,7 @@ from amt.api.ai_act_profile import get_ai_act_profile_selector from amt.api.deps import templates +from amt.api.lifecycles import get_lifecycles from amt.api.navigation import Navigation, resolve_base_navigation_items, resolve_navigation_items from amt.schema.project import ProjectNew from amt.services.instruments import InstrumentsService @@ -61,6 +62,7 @@ async def get_new( "ai_act_profile": ai_act_profile, "breadcrumbs": breadcrumbs, "sub_menu_items": {}, # sub_menu_items disabled for now, + "lifecycles": get_lifecycles(request), } response = templates.TemplateResponse(request, "projects/new.html.j2", context) diff --git a/amt/locale/base.pot b/amt/locale/base.pot index 67deec0d..81c81140 100644 --- a/amt/locale/base.pot +++ b/amt/locale/base.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-10 11:00+0200\n" +"POT-Creation-Date: 2024-10-10 21:27+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -41,6 +41,42 @@ msgstr "" msgid "Role" msgstr "" +#: amt/api/lifecycles.py:39 +msgid "Organizational Responsibilities" +msgstr "" + +#: amt/api/lifecycles.py:40 +msgid "Problem Analysis" +msgstr "" + +#: amt/api/lifecycles.py:41 +msgid "Design" +msgstr "" + +#: amt/api/lifecycles.py:42 +msgid "Data Exploration and Preparation" +msgstr "" + +#: amt/api/lifecycles.py:43 +msgid "Development" +msgstr "" + +#: amt/api/lifecycles.py:44 +msgid "Verification and Validation" +msgstr "" + +#: amt/api/lifecycles.py:45 +msgid "Implementation" +msgstr "" + +#: amt/api/lifecycles.py:46 +msgid "Monitoring and Management" +msgstr "" + +#: amt/api/lifecycles.py:47 +msgid "Phasing Out" +msgstr "" + #: amt/api/navigation.py:45 msgid "Home" msgstr "" @@ -97,7 +133,7 @@ msgstr "" msgid "Model" msgstr "" -#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:114 +#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:134 msgid "Instruments" msgstr "" @@ -304,11 +340,31 @@ msgstr "" msgid "Your project name here" msgstr "" -#: amt/site/templates/projects/new.html.j2:35 +#: amt/site/templates/projects/new.html.j2:37 +msgid "Lifecycle" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Select the lifecycle your project is currently in" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Read" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Algorithm Framework on lifecycles" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "for background information" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:55 msgid "AI Act Profile" msgstr "" -#: amt/site/templates/projects/new.html.j2:37 +#: amt/site/templates/projects/new.html.j2:57 msgid "" "The AI Act profile provides insight into, among other things, the type of" " AI system and the associated obligations from the European AI Act. If " @@ -317,33 +373,33 @@ msgid "" "tree." msgstr "" -#: amt/site/templates/projects/new.html.j2:42 +#: amt/site/templates/projects/new.html.j2:62 msgid "Find your AI Act profile" msgstr "" -#: amt/site/templates/projects/new.html.j2:97 +#: amt/site/templates/projects/new.html.j2:117 msgid "Yes" msgstr "" -#: amt/site/templates/projects/new.html.j2:107 +#: amt/site/templates/projects/new.html.j2:127 msgid "No" msgstr "" -#: amt/site/templates/projects/new.html.j2:116 +#: amt/site/templates/projects/new.html.j2:136 msgid "" "Overview of instruments for the responsible development, deployment, " "assessment and monitoring of algorithms and AI-systems." msgstr "" -#: amt/site/templates/projects/new.html.j2:124 +#: amt/site/templates/projects/new.html.j2:144 msgid "Choose one or more instruments" msgstr "" -#: amt/site/templates/projects/new.html.j2:138 +#: amt/site/templates/projects/new.html.j2:158 msgid "Create Project" msgstr "" -#: amt/site/templates/projects/new.html.j2:152 +#: amt/site/templates/projects/new.html.j2:172 msgid "Copy results and close" msgstr "" diff --git a/amt/locale/en_US/LC_MESSAGES/messages.mo b/amt/locale/en_US/LC_MESSAGES/messages.mo index 888525f5..e7be948a 100644 Binary files a/amt/locale/en_US/LC_MESSAGES/messages.mo and b/amt/locale/en_US/LC_MESSAGES/messages.mo differ diff --git a/amt/locale/en_US/LC_MESSAGES/messages.po b/amt/locale/en_US/LC_MESSAGES/messages.po index a6c51330..6d136cba 100644 --- a/amt/locale/en_US/LC_MESSAGES/messages.po +++ b/amt/locale/en_US/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-10 11:00+0200\n" +"POT-Creation-Date: 2024-10-10 21:27+0200\n" "PO-Revision-Date: 2024-07-25 21:01+0200\n" "Last-Translator: FULL NAME \n" "Language: en_US\n" @@ -42,6 +42,42 @@ msgstr "" msgid "Role" msgstr "" +#: amt/api/lifecycles.py:39 +msgid "Organizational Responsibilities" +msgstr "" + +#: amt/api/lifecycles.py:40 +msgid "Problem Analysis" +msgstr "" + +#: amt/api/lifecycles.py:41 +msgid "Design" +msgstr "" + +#: amt/api/lifecycles.py:42 +msgid "Data Exploration and Preparation" +msgstr "" + +#: amt/api/lifecycles.py:43 +msgid "Development" +msgstr "" + +#: amt/api/lifecycles.py:44 +msgid "Verification and Validation" +msgstr "" + +#: amt/api/lifecycles.py:45 +msgid "Implementation" +msgstr "" + +#: amt/api/lifecycles.py:46 +msgid "Monitoring and Management" +msgstr "" + +#: amt/api/lifecycles.py:47 +msgid "Phasing Out" +msgstr "" + #: amt/api/navigation.py:45 msgid "Home" msgstr "" @@ -98,7 +134,7 @@ msgstr "" msgid "Model" msgstr "" -#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:114 +#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:134 msgid "Instruments" msgstr "" @@ -305,11 +341,31 @@ msgstr "" msgid "Your project name here" msgstr "" -#: amt/site/templates/projects/new.html.j2:35 +#: amt/site/templates/projects/new.html.j2:37 +msgid "Lifecycle" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Select the lifecycle your project is currently in" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Read" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Algorithm Framework on lifecycles" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "for background information" +msgstr "" + +#: amt/site/templates/projects/new.html.j2:55 msgid "AI Act Profile" msgstr "" -#: amt/site/templates/projects/new.html.j2:37 +#: amt/site/templates/projects/new.html.j2:57 msgid "" "The AI Act profile provides insight into, among other things, the type of" " AI system and the associated obligations from the European AI Act. If " @@ -318,42 +374,33 @@ msgid "" "tree." msgstr "" -#: amt/site/templates/projects/new.html.j2:42 +#: amt/site/templates/projects/new.html.j2:62 msgid "Find your AI Act profile" msgstr "" -#: amt/site/templates/projects/new.html.j2:97 +#: amt/site/templates/projects/new.html.j2:117 msgid "Yes" msgstr "" -#: amt/site/templates/projects/new.html.j2:107 +#: amt/site/templates/projects/new.html.j2:127 msgid "No" msgstr "" -#: amt/site/templates/projects/new.html.j2:116 +#: amt/site/templates/projects/new.html.j2:136 msgid "" "Overview of instruments for the responsible development, deployment, " "assessment and monitoring of algorithms and AI-systems." msgstr "" -#: amt/site/templates/projects/new.html.j2:124 +#: amt/site/templates/projects/new.html.j2:144 msgid "Choose one or more instruments" msgstr "" -#: amt/site/templates/projects/new.html.j2:138 +#: amt/site/templates/projects/new.html.j2:158 msgid "Create Project" msgstr "" -#: amt/site/templates/projects/new.html.j2:152 +#: amt/site/templates/projects/new.html.j2:172 msgid "Copy results and close" msgstr "" -#~ msgid "TEST" -#~ msgstr "" - -#~ msgid "Algorithmic Management Toolkit (AMT)" -#~ msgstr "" - -#~ msgid "done" -#~ msgstr "" - diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.mo b/amt/locale/nl_NL/LC_MESSAGES/messages.mo index f675f2e1..217cf3e2 100644 Binary files a/amt/locale/nl_NL/LC_MESSAGES/messages.mo and b/amt/locale/nl_NL/LC_MESSAGES/messages.mo differ diff --git a/amt/locale/nl_NL/LC_MESSAGES/messages.po b/amt/locale/nl_NL/LC_MESSAGES/messages.po index 9cf6c9c3..c0897b60 100644 --- a/amt/locale/nl_NL/LC_MESSAGES/messages.po +++ b/amt/locale/nl_NL/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-10-10 11:00+0200\n" +"POT-Creation-Date: 2024-10-10 21:27+0200\n" "PO-Revision-Date: 2024-07-25 21:01+0200\n" "Last-Translator: FULL NAME \n" "Language: nl_NL\n" @@ -42,6 +42,42 @@ msgstr "Zijn er transparantieverplichtingen?" msgid "Role" msgstr "Rol" +#: amt/api/lifecycles.py:39 +msgid "Organizational Responsibilities" +msgstr "Organisatieverantwoordelijkheden" + +#: amt/api/lifecycles.py:40 +msgid "Problem Analysis" +msgstr "Probleemanalyse" + +#: amt/api/lifecycles.py:41 +msgid "Design" +msgstr "Ontwerpen" + +#: amt/api/lifecycles.py:42 +msgid "Data Exploration and Preparation" +msgstr "Dataverkenning en datapreparatie" + +#: amt/api/lifecycles.py:43 +msgid "Development" +msgstr "Ontwikkelen" + +#: amt/api/lifecycles.py:44 +msgid "Verification and Validation" +msgstr "Verficatie en validatie" + +#: amt/api/lifecycles.py:45 +msgid "Implementation" +msgstr "Implementeren" + +#: amt/api/lifecycles.py:46 +msgid "Monitoring and Management" +msgstr "Monitoring en beheer" + +#: amt/api/lifecycles.py:47 +msgid "Phasing Out" +msgstr "Uitfaseren" + #: amt/api/navigation.py:45 msgid "Home" msgstr "Start" @@ -98,7 +134,7 @@ msgstr "Data" msgid "Model" msgstr "Model" -#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:114 +#: amt/api/navigation.py:59 amt/site/templates/projects/new.html.j2:134 msgid "Instruments" msgstr "Instrumenten" @@ -311,11 +347,31 @@ msgstr "Project naam" msgid "Your project name here" msgstr "Jouw projectnaam hier" -#: amt/site/templates/projects/new.html.j2:35 +#: amt/site/templates/projects/new.html.j2:37 +msgid "Lifecycle" +msgstr "Levenscyclus" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Select the lifecycle your project is currently in" +msgstr "Selecteer de levenscyclus van je project" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Read" +msgstr "Lees" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "Algorithm Framework on lifecycles" +msgstr "Algoritmekader over levenscyclus" + +#: amt/site/templates/projects/new.html.j2:38 +msgid "for background information" +msgstr "voor achtergrond informatie" + +#: amt/site/templates/projects/new.html.j2:55 msgid "AI Act Profile" msgstr "AI Verordening Profiel" -#: amt/site/templates/projects/new.html.j2:37 +#: amt/site/templates/projects/new.html.j2:57 msgid "" "The AI Act profile provides insight into, among other things, the type of" " AI system and the associated obligations from the European AI Act. If " @@ -323,23 +379,23 @@ msgid "" "Otherwise, you can find your AI Act Profile with the AI Act Decision " "tree." msgstr "" -"Het profiel van je toepassing, gebasseerd op de AI Act, geeft inzicht in " +"Het profiel van je toepassing, gebaseerd op de AI Act, geeft inzicht in " "onder andere het type AI systeem, de regelgeving die van toepassing is en" " de risicocategorie." -#: amt/site/templates/projects/new.html.j2:42 +#: amt/site/templates/projects/new.html.j2:62 msgid "Find your AI Act profile" msgstr "Vind uw AI Act profiel" -#: amt/site/templates/projects/new.html.j2:97 +#: amt/site/templates/projects/new.html.j2:117 msgid "Yes" msgstr "Ja" -#: amt/site/templates/projects/new.html.j2:107 +#: amt/site/templates/projects/new.html.j2:127 msgid "No" msgstr "Nee" -#: amt/site/templates/projects/new.html.j2:116 +#: amt/site/templates/projects/new.html.j2:136 msgid "" "Overview of instruments for the responsible development, deployment, " "assessment and monitoring of algorithms and AI-systems." @@ -347,24 +403,15 @@ msgstr "" "Overzicht van aanbevolen instrument voor het verantwoord ontwikkelen, " "gebruiken, beoordelen en monitoren van algoritmes en AI-systemen." -#: amt/site/templates/projects/new.html.j2:124 +#: amt/site/templates/projects/new.html.j2:144 msgid "Choose one or more instruments" msgstr "Kies één of meerdere instrumenten" -#: amt/site/templates/projects/new.html.j2:138 +#: amt/site/templates/projects/new.html.j2:158 msgid "Create Project" msgstr "Maak project" -#: amt/site/templates/projects/new.html.j2:152 +#: amt/site/templates/projects/new.html.j2:172 msgid "Copy results and close" msgstr "Resultaten overnemen en sluiten" -#~ msgid "TEST" -#~ msgstr "" - -#~ msgid "Algorithmic Management Toolkit (AMT)" -#~ msgstr "Algoritme Management Toolkit (AMT)" - -#~ msgid "done" -#~ msgstr "Afgerond" - diff --git a/amt/migrations/versions/14240ff670e2_add_lifecycle.py b/amt/migrations/versions/14240ff670e2_add_lifecycle.py new file mode 100644 index 00000000..e3617241 --- /dev/null +++ b/amt/migrations/versions/14240ff670e2_add_lifecycle.py @@ -0,0 +1,50 @@ +"""Add lifecycle field to project table + +Revision ID: 14240ff670e2 +Revises: 66cf279a7f62 +Create Date: 2024-10-10 16:26:52.294477 + +""" + +from collections.abc import Sequence + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = "14240ff670e2" +down_revision: str | None = "66cf279a7f62" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + +# Define the Lifecycle enum values +lifecycle_values = [ + 'ORGANIZATIONAL_RESPONSIBILITIES', + 'PROBLEM_ANALYSIS', + 'DESIGN', + 'DATA_EXPLORATION_AND_PREPARATION', + 'DEVELOPMENT', + 'VERIFICATION_AND_VALIDATION', + 'IMPLEMENTATION', + 'MONITORING_AND_MANAGEMENT', + 'PHASING_OUT' +] + + +def upgrade() -> None: + # Create the enum type + lifecycle_enum = postgresql.ENUM(*lifecycle_values, name='lifecycle') + lifecycle_enum.create(op.get_bind()) + + # Add the lifecycle column + op.add_column('project', sa.Column('lifecycle', lifecycle_enum, nullable=True)) + + +def downgrade() -> None: + # Remove the lifecycle column + op.drop_column('project', 'lifecycle') + + # Drop the enum type + lifecycle_enum = postgresql.ENUM(*lifecycle_values, name='lifecycle') + lifecycle_enum.drop(op.get_bind()) diff --git a/amt/models/project.py b/amt/models/project.py index 8252abf8..225a19f9 100644 --- a/amt/models/project.py +++ b/amt/models/project.py @@ -1,8 +1,10 @@ from typing import TypeVar from sqlalchemy import String +from sqlalchemy.dialects.postgresql import ENUM from sqlalchemy.orm import Mapped, mapped_column +from amt.api.lifecycles import Lifecycles from amt.models.base import Base T = TypeVar("T", bound="Project") @@ -12,5 +14,6 @@ class Project(Base): __tablename__ = "project" id: Mapped[int] = mapped_column(primary_key=True) - name: Mapped[str] = mapped_column(String(255)) # TODO: (Christopher) how to set min_length? + name: Mapped[str] = mapped_column(String(255)) + lifecycle: Mapped[Lifecycles | None] = mapped_column(ENUM(Lifecycles), nullable=True) model_card: Mapped[str | None] = mapped_column(default=None) diff --git a/amt/schema/lifecycle.py b/amt/schema/lifecycle.py new file mode 100644 index 00000000..5ef405dc --- /dev/null +++ b/amt/schema/lifecycle.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel + + +class Lifecycle(BaseModel): + id: str + name: str diff --git a/amt/schema/project.py b/amt/schema/project.py index bd6dc19e..f9ea2ff9 100644 --- a/amt/schema/project.py +++ b/amt/schema/project.py @@ -4,6 +4,7 @@ class ProjectBase(BaseModel): name: str = Field(min_length=3, max_length=255) + lifecycle: str = Field() class ProjectNew(ProjectBase): diff --git a/amt/services/projects.py b/amt/services/projects.py index 18602692..ca1ded72 100644 --- a/amt/services/projects.py +++ b/amt/services/projects.py @@ -31,7 +31,7 @@ def get(self, project_id: int) -> Project: return self.repository.find_by_id(project_id) def create(self, project_new: ProjectNew) -> Project: - project = Project(name=project_new.name) + project = Project(name=project_new.name, lifecycle=project_new.lifecycle) self.repository.save(project) diff --git a/amt/site/templates/projects/details_info.html.j2 b/amt/site/templates/projects/details_info.html.j2 index 943e2cae..33229d4f 100644 --- a/amt/site/templates/projects/details_info.html.j2 +++ b/amt/site/templates/projects/details_info.html.j2 @@ -33,7 +33,7 @@ role="img" aria-label="Bevestiging" > - {{ system_card.status }} + {{ lifecycle.name }} diff --git a/amt/site/templates/projects/new.html.j2 b/amt/site/templates/projects/new.html.j2 index 661695ff..c1bf5992 100644 --- a/amt/site/templates/projects/new.html.j2 +++ b/amt/site/templates/projects/new.html.j2 @@ -30,6 +30,26 @@ dir="auto" value="" /> +
+
+ +

{% trans %}Select the lifecycle your project is currently in{% endtrans %}. {% trans %}Read{% endtrans %} {% trans %}Algorithm Framework on lifecycles{% endtrans %} {% trans %}for background information{% endtrans %}.

+
+ {% for lifecycle in lifecycles %} +
+ +
+ {% endfor %} +

{% trans %}AI Act Profile{% endtrans %}

diff --git a/tests/api/routes/test_projects.py b/tests/api/routes/test_projects.py index eb9c667d..a42e0992 100644 --- a/tests/api/routes/test_projects.py +++ b/tests/api/routes/test_projects.py @@ -77,6 +77,7 @@ def test_post_new_projects( client.cookies["fastapi-csrf-token"] = "1" new_project = ProjectNew( name="default project", + lifecycle="DESIGN", type="AI-systeem", open_source="open-source", publication_category="hoog-risico AI", @@ -103,6 +104,7 @@ def test_post_new_projects_write_system_card( FileSystemStorageService.write = MagicMock() project_new = ProjectNew( name="name1", + lifecycle="DESIGN", type="AI-systeem", open_source="open-source", publication_category="hoog-risico AI", diff --git a/tests/core/test_exception_handlers.py b/tests/core/test_exception_handlers.py index 25df0994..230ef444 100644 --- a/tests/core/test_exception_handlers.py +++ b/tests/core/test_exception_handlers.py @@ -21,7 +21,7 @@ def test_request_validation_exception_handler(client: TestClient): def test_request_csrf_protect_exception_handler_invalid_token_in_header(client: TestClient): data = client.get("/projects/new") - new_project = ProjectNew(name="default project") + new_project = ProjectNew(name="default project", lifecycle="DATA_EXPLORATION_AND_PREPARATION") with pytest.raises(AMTCSRFProtectError): _response = client.post( "/projects/new", json=new_project.model_dump(), headers={"X-CSRF-Token": "1"}, cookies=data.cookies @@ -44,7 +44,7 @@ def test_request_validation_exception_handler_htmx(client: TestClient): def test_request_csrf_protect_exception_handler_invalid_token(client: TestClient): data = client.get("/projects/new") - new_project = ProjectNew(name="default project") + new_project = ProjectNew(name="default project", lifecycle="DATA_EXPLORATION_AND_PREPARATION") with pytest.raises(AMTCSRFProtectError): _response = client.post( "/projects/new", diff --git a/tests/e2e/test_create_project.py b/tests/e2e/test_create_project.py index 8edcdafe..cf3cbda3 100644 --- a/tests/e2e/test_create_project.py +++ b/tests/e2e/test_create_project.py @@ -8,6 +8,9 @@ def test_e2e_create_project(page: Page): page.fill("#name", "My new project") + button = page.locator("#lifecycle-DATA_EXPLORATION_AND_PREPARATION") + button.click() + impact_assessment = page.get_by_label("AI Impact Assessment (AIIA)") expect(impact_assessment).not_to_be_checked() @@ -54,6 +57,9 @@ def test_e2e_create_project_with_tasks(page: Page): page.fill("#name", "My new filled project") + button = page.locator("#lifecycle-DATA_EXPLORATION_AND_PREPARATION") + button.click() + impact_assessment = page.get_by_label("AI Impact Assessment (AIIA)") expect(impact_assessment).not_to_be_checked() diff --git a/tests/schema/test_schema_project.py b/tests/schema/test_schema_project.py index fb32eeb3..10b934d0 100644 --- a/tests/schema/test_schema_project.py +++ b/tests/schema/test_schema_project.py @@ -4,6 +4,7 @@ def test_project_schema_create_new(): project_new = ProjectNew( name="Project Name", + lifecycle="DATA_EXPLORATION_AND_PREPARATION", instruments=["urn:instrument:1", "urn:instrument:2"], type="AI-systeem", open_source="open-source", @@ -25,6 +26,7 @@ def test_project_schema_create_new(): def test_project_schema_create_new_one_instrument(): project_new = ProjectNew( name="Project Name", + lifecycle="DATA_EXPLORATION_AND_PREPARATION", instruments="urn:instrument:1", type="AI-systeem", open_source="open-source", diff --git a/tests/services/test_projects_service.py b/tests/services/test_projects_service.py index 0b02c41c..9fd27a5c 100644 --- a/tests/services/test_projects_service.py +++ b/tests/services/test_projects_service.py @@ -14,6 +14,7 @@ def test_get_project(): # Given project_id = 1 project_name = "Project 1" + project_lifecycle = "development" project_model_card = "model_card_path" projects_service = ProjectsService( repository=Mock(spec=ProjectsRepository), @@ -21,7 +22,7 @@ def test_get_project(): instrument_service=Mock(spec=InstrumentsService), ) projects_service.repository.find_by_id.return_value = Project( # type: ignore - id=project_id, name=project_name, model_card=project_model_card + id=project_id, name=project_name, lifecycle=project_lifecycle, model_card=project_model_card ) # When @@ -30,6 +31,7 @@ def test_get_project(): # Then assert project.id == project_id assert project.name == project_name + assert project.lifecycle == project_lifecycle assert project.model_card == project_model_card projects_service.repository.find_by_id.assert_called_once_with(project_id) # type: ignore @@ -37,6 +39,7 @@ def test_get_project(): def test_create_project(): project_id = 1 project_name = "Project 1" + project_lifecycle = "development" project_model_card = Path("model_card_path") projects_service = ProjectsService( repository=Mock(spec=ProjectsRepository), @@ -44,13 +47,14 @@ def test_create_project(): instrument_service=Mock(spec=InstrumentsService), ) projects_service.repository.save.return_value = Project( # type: ignore - id=project_id, name=project_name, model_card=str(project_model_card) + id=project_id, name=project_name, lifecycle=project_lifecycle, model_card=str(project_model_card) ) projects_service.instrument_service.fetch_instruments.return_value = [default_instrument()] # type: ignore # When project_new = ProjectNew( name=project_name, + lifecycle=project_lifecycle, instruments=[], type="project_type", open_source="project_open_source", @@ -64,4 +68,5 @@ def test_create_project(): # Then assert project.id == project_id assert project.name == project_name + assert project.lifecycle == project_lifecycle projects_service.repository.save.assert_called() # type: ignore