"""Removing a holding, and what stops it. The requirement: you must be able to remove a holding added by accident, it must not have any trades to be removed … if I hover over the delete button it should tell me why." Two things make this more than a delete button. * **Instruments are shared.** The list, and the price history with it, belongs to everyone using the tracker. So removal *deactivates* rather than deletes, and the "is anything recorded against it" question has to be asked of every portfolio — not just the one asking. * **But the answer must not leak.** The panel lists the asking portfolio's own trades, with links; anything belonging to somebody else is counted and never shown. """ from __future__ import annotations import re from sqlalchemy import select import factories as fac from app.models import Instrument from test_routes import bind_to_only_portfolio, make_login, session_csrf HTML = {"accept": "text/html"} def _page(client) -> str: response = client.get("/holdings", headers=HTML) assert response.status_code == 200 return response.text def test_an_untraded_instrument_offers_a_remove_button(client, session_factory): make_login(client, session_factory) with session_factory() as s: fac.hold(s, fac.make_instrument(s, "SPARE")) s.commit() page = _page(client) assert re.search(r'action="/holdings/\d+/remove"', page), "no Remove control" def test_removing_one_asks_first_and_says_what_goes(client, session_factory): """It went at a click, its note and reinvest setting with it.""" make_login(client, session_factory) with session_factory() as s: fac.hold(s, fac.make_instrument(s, "SPARE")) s.commit() page = _page(client) assert re.search(r'