from collections import namedtuple from urllib.parse import urlparse import pytest from bs4 import BeautifulSoup from flask import render_template, url_for from atlas_um.pgdb import Product, DNAAccountStatuses, DNAAccountActivity from tests.atlas_um.factories import ( ClaimNameFactory, ClaimValueFactory, DNAAccountFactory, ResourceGroupFactory, ) from . import helpers class TestShowProduct: FAKE_HOST = "atlas_um.test" @pytest.fixture def app_config(self): def inner(app): app.config["SERVER_NAME"] = self.FAKE_HOST return inner def test_titles(self, app, pgdb_session): context = self.build_render_context(pgdb_session) with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) account = context.account product_name = context.product.name assert ( page.title.get_text(strip=True) == f"{account.given_name} {account.family_name}: {product_name}" ) page_head = page.find(id="subnav-header") vip_text = "VIP" if account.is_vip else "" assert ( page_head.get_text(strip=True) == f"{account.given_name} {account.family_name}" f"{vip_text}{account.status}EXTERNAL" ) subheader = page.find(class_="details-header-with-extra") assert subheader.get_text(strip=True) == product_name def test_sidebar(self, app, pgdb_session): context = self.build_render_context(pgdb_session) with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) sidebar = page.find(class_="left-sidebar") assert sidebar is not None for group, _ in context.account.resource_groups_with_status: url = self.urlspec_for_this( app, account=context.account, product_code=group.id ) actual_link = sidebar.find("a", attrs={"href": url}) assert actual_link is not None assert actual_link.get_text(strip=True) == group.name def test_no_claim_names(self, app, pgdb_session): account = DNAAccountFactory.build() resource_group = ResourceGroupFactory.build() pgdb_session.add(resource_group) product = Product(resource_group=resource_group, account=account) Context = namedtuple("Context", "account product DNAAccountStatuses") context = Context(account, product, DNAAccountStatuses) pgdb_session.add(context.account) pgdb_session.commit() with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): pgdb_session.add(account) pgdb_session.commit() page = self.render_soup(**context._asdict()) actual = page.select_one(".product-details").get_text(strip=True) assert actual == "No settings available" def test_claims(self, app, pgdb_session): context = self.build_render_context(pgdb_session) with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) for claim_name, claim_values in context.product.claims.items(): actual_friendly = page.select_one( f"[data-element-name={claim_name.internal_name}]>label" ).get_text(strip=True) actual_value = page.select_one( f"[data-element-name={claim_name.internal_name}]>.value" ).get_text(strip=True) assert ( actual_friendly == claim_name.friendly ), "Wrong friendly name" assert actual_value == "N/A", "Wrong claim value" def test_status_active(self, app, pgdb_session, faker): context = self.build_render_context(pgdb_session) product = context.product product.is_disabled = False product.created_at = faker.date_time() product.updated_at = faker.date_time() with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) edit_button = page.find(id="edit-button") assert edit_button.get_text(strip=True) == "Edit" created_at = page.find(id="created_at") assert created_at.get_text(strip=True) == product.created_at.strftime( "%m/%d/%y, %-I:%M %p" ) created_at_label = page.select_one( "[data-element-name=created_at]>label" ) assert created_at_label.get_text(strip=True) == "Enabled" updated_at = page.find(id="updated_at") assert updated_at.get_text(strip=True) == product.updated_at.strftime( "%m/%d/%y, %-I:%M %p" ) updated_at_label = page.select_one( "[data-element-name=updated_at]>label" ) assert updated_at_label.get_text(strip=True) == "Last modified" def test_status_disabled(self, app, pgdb_session, faker): context = self.build_render_context(pgdb_session) product = context.product product.is_disabled = True product.created_at = faker.date_time() product.updated_at = faker.date_time() with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) edit_button = page.find(id="edit-button") assert edit_button.get_text(strip=True) == "Enable" created_at = page.find(id="created_at") assert created_at.get_text(strip=True) == product.created_at.strftime( "%m/%d/%y, %-I:%M %p" ) created_at_label = page.select_one( "[data-element-name=created_at]>label" ) assert created_at_label.get_text(strip=True) == "First enabled" updated_at = page.find(id="updated_at") assert updated_at.get_text(strip=True) == product.updated_at.strftime( "%m/%d/%y, %-I:%M %p" ) updated_at_label = page.select_one( "[data-element-name=updated_at]>label" ) assert updated_at_label.get_text(strip=True) == "Disabled" def test_last_login(self, app, pgdb_session, faker): context = self.build_render_context(pgdb_session) product = context.product with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) last_login = page.find(id="last_login") assert last_login.get_text(strip=True) == product.last_login.strftime( "%m/%d/%y, %-I:%M %p" ) last_login_label = page.select_one( "[data-element-name=last_login]>label" ) assert last_login_label.get_text(strip=True) == "Last login" def test_first_login(self, app, pgdb_session, faker): context = self.build_render_context(pgdb_session) product = context.product with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) first_login = page.find(id="first_login") assert first_login.get_text( strip=True ) == product.first_login.strftime("%m/%d/%y, %-I:%M %p") first_login_label = page.select_one( "[data-element-name=first_login]>label" ) assert first_login_label.get_text(strip=True) == "First login" def test_last_activity(self, app, pgdb_session, faker): context = self.build_render_context(pgdb_session) product = context.product with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) last_activity = page.find(id="last_activity") assert last_activity.get_text( strip=True ) == product.last_activity.strftime("%m/%d/%y, %-I:%M %p") last_activity_label = page.select_one( "[data-element-name=last_activity]>label" ) assert last_activity_label.get_text(strip=True) == "Last activity" def test_copyright_notice( self, app, pgdb_session, expected_copyright_notice ): context = self.build_render_context(pgdb_session) with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) footer = page.find("footer") copyright_notice = footer.find(id="copyright-notice") assert ( copyright_notice.get_text(strip=True) == expected_copyright_notice ) def test_frontend_libs_are_added( self, app, pgdb_session, expected_copyright_notice ): context = self.build_render_context(pgdb_session) with app.test_request_context( self.url_for_this(app, context.account, context.product.code) ): page = self.render_soup(**context._asdict()) assert all(helpers.added_frontend_libs(page)) # Helpers def build_render_context(self, pgdb_session): account = DNAAccountFactory.build() pgdb_session.add(account) pgdb_session.commit() claim_name = ClaimNameFactory.build( claim_values_serializer="BooleanAnd", resource_group__service_url=f"https://{self.FAKE_HOST}", ) claim_value = ClaimValueFactory.build( claim_name=claim_name, components={"value1": 1} ) pgdb_session.add(claim_value) account_last_login = DNAAccountActivity.register_for_resource_group( account, claim_name.resource_group ) product = Product( resource_group=claim_name.resource_group, account=account ) Context = namedtuple( "Context", "account product DNAAccountStatuses last_login" ) return Context( account, product, DNAAccountStatuses, account_last_login.last_login ) def url_for_this(self, app, account, product_code, **kwargs): kwargs["endpoint"] = "dna_accounts.show_product" kwargs["account_id"] = account.id kwargs["product_code"] = product_code with app.app_context(): u = url_for(**kwargs) return u def urlspec_for_this(self, app, **kwargs): u = urlparse(self.url_for_this(app, **kwargs)) return u._replace(scheme="", netloc="") def render_soup(self, **kwargs): rt = render_template("dna_accounts/show_product.html", **kwargs) return BeautifulSoup(rt, "html.parser")