"""What a knowledge base article's topic decides about seeing the article. An article's topic is an Application. When that application is retired the article describes something no longer in service, and showing it beside live documentation reads as though it were current - so it does not show at all. `isactive` is the ONLY property of an application that decides this. In particular `ishidden`, which governs whether an application appears on the tiles page, says nothing about whether it can be the subject of an article. """ import pytest from shopdb.core.models import Application from plugins.knowledgebase.models import KnowledgeBase @pytest.fixture def library(db): """One application of each interesting shape, with an article each.""" applications = { 'live': Application(appname='Live App', isinstallable=True, ishidden=False, isactive=True), 'notinstallable': Application(appname='Manual App', isinstallable=False, ishidden=False, isactive=True), 'hidden': Application(appname='Hidden App', isinstallable=False, ishidden=True, isactive=True), 'retired': Application(appname='Retired App', isinstallable=True, ishidden=False, isactive=False), } db.session.add_all(applications.values()) db.session.flush() articles = { 'live': KnowledgeBase(shortdescription='Live runbook', linkurl='u', appid=applications['live'].appid, clicks=3, isactive=True), 'hidden': KnowledgeBase(shortdescription='Hidden runbook', linkurl='u', appid=applications['hidden'].appid, clicks=2, isactive=True), 'retired': KnowledgeBase(shortdescription='Retired runbook', linkurl='u', appid=applications['retired'].appid, clicks=5, isactive=True), 'topicless': KnowledgeBase(shortdescription='General note', linkurl='u', appid=None, clicks=1, isactive=True), } db.session.add_all(articles.values()) db.session.commit() return {'applications': applications, 'articles': articles} def titles(client, url='/api/knowledgebase'): return sorted(row['shortdescription'] for row in client.get(url).get_json()['data']) def test_an_article_about_a_retired_application_does_not_show(client, library): assert 'Retired runbook' not in titles(client) def test_an_article_with_no_topic_still_shows(client, library): """A null topic is not a retired one. Not every article is about an application, and those must not be collateral damage.""" assert 'General note' in titles(client) def test_a_hidden_application_is_still_a_valid_topic(client, library): """ishidden keeps an application off the tiles page. It says nothing about documentation, and isactive is the only filter that applies here.""" assert 'Hidden runbook' in titles(client) def test_searching_a_retired_application_name_finds_nothing(client, library): """The topic search matched on application name without checking isactive, which surfaced retired articles and printed the retired application as their subject.""" assert titles(client, '/api/knowledgebase?search=Retired App') == [] def test_searching_a_title_does_not_resurrect_a_retired_article(client, library): """Hiding it from the list and finding it by title would be no rule at all.""" found = titles(client, '/api/knowledgebase?search=runbook') assert 'Retired runbook' not in found assert 'Live runbook' in found def test_the_counts_agree_with_the_list(client, library): """A total that includes articles nobody can see is a total nobody can reconcile against the page.""" visible = titles(client) stats = client.get('/api/knowledgebase/stats').get_json()['data'] total = stats.get('total_articles', stats.get('totalarticles')) clicks = stats.get('total_clicks', stats.get('totalclicks')) assert total == len(visible) == 3 # 3 + 2 + 1 from the live, hidden-topic and topicless articles; the retired # article's 5 clicks are excluded along with the article. assert clicks == 6 def test_the_topic_list_offers_every_active_application(client, library): """What the article form's topic dropdown fetches. Installable or not, hidden or not - only retired is excluded.""" offered = sorted(row['appname'] for row in client.get( '/api/applications?perpage=100&showhidden=true').get_json()['data']) assert offered == ['Hidden App', 'Live App', 'Manual App'] assert 'Retired App' not in offered