import pytest from pytest import raises from sqlalchemy.exc import IntegrityError from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub from ereuse_devicehub.resources.agent.models import Organization from ereuse_devicehub.resources.device.models import Desktop from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.tag import Tag from ereuse_devicehub.resources.tag.view import CannotCreateETag, TagNotLinked from teal.db import MultipleResourcesFound, ResourceNotFound from teal.marshmallow import ValidationError from tests import conftest @pytest.mark.usefixtures(conftest.app_context.__name__) def test_create_tag(): """Creates a tag specifying a custom organization.""" org = Organization(name='Bar', tax_id='BarTax') tag = Tag(id='bar-1', org=org) db.session.add(tag) db.session.commit() @pytest.mark.usefixtures(conftest.app_context.__name__) def test_create_tag_default_org(): """Creates a tag using the default organization.""" tag = Tag(id='foo-1') assert not tag.org_id, 'org-id is set as default value so it should only load on flush' # We don't want the organization to load, or it would make this # object, from transient to new (added to session) assert 'org' not in vars(tag), 'Organization should not have been loaded' db.session.add(tag) db.session.commit() assert tag.org.name == 'FooOrg' # as defined in the settings @pytest.mark.usefixtures(conftest.app_context.__name__) def test_create_tag_no_slash(): """Checks that no tags can be created that contain a slash.""" with raises(ValidationError): Tag(id='/') @pytest.mark.usefixtures(conftest.app_context.__name__) def test_create_two_same_tags(): """Ensures there cannot be two tags with the same ID and organization.""" db.session.add(Tag(id='foo-bar')) db.session.add(Tag(id='foo-bar')) with raises(IntegrityError): db.session.commit() db.session.rollback() # And it works if tags are in different organizations db.session.add(Tag(id='foo-bar')) org2 = Organization(name='org 2', tax_id='tax id org 2') db.session.add(Tag(id='foo-bar', org=org2)) db.session.commit() def test_tag_post(app: Devicehub, user: UserClient): """Checks the POST method of creating a tag.""" user.post(res=Tag, query=[('ids', 'foo')], data={}) with app.app_context(): assert Tag.query.filter_by(id='foo').one() def test_tag_post_etag(user: UserClient): """ Ensures users cannot create eReuse.org tags through POST; only terminal. """ user.post(res=Tag, query=[('ids', 'FO-123456')], data={}, status=CannotCreateETag) # Although similar, these are not eTags and should pass user.post(res=Tag, query=[ ('ids', 'FO-0123-45'), ('ids', 'FOO012345678910'), ('ids', 'FO'), ('ids', 'FO-'), ('ids', 'FO-123'), ('ids', 'FOO-123456') ], data={}) def test_tag_get_device_from_tag_endpoint(app: Devicehub, user: UserClient): """Checks getting a linked device from a tag endpoint""" with app.app_context(): # Create a pc with a tag tag = Tag(id='foo-bar') pc = Desktop(serial_number='sn1', chassis=ComputerChassis.Tower) pc.tags.add(tag) db.session.add(pc) db.session.commit() computer, _ = user.get(res=Tag, item='foo-bar/device') assert computer['serialNumber'] == 'sn1' def test_tag_get_device_from_tag_endpoint_no_linked(app: Devicehub, user: UserClient): """As above, but when the tag is not linked.""" with app.app_context(): db.session.add(Tag(id='foo-bar')) db.session.commit() user.get(res=Tag, item='foo-bar/device', status=TagNotLinked) def test_tag_get_device_from_tag_endpoint_no_tag(user: UserClient): """As above, but when there is no tag with such ID.""" user.get(res=Tag, item='foo-bar/device', status=ResourceNotFound) def test_tag_get_device_from_tag_endpoint_multiple_tags(app: Devicehub, user: UserClient): """ As above, but when there are two tags with the same ID, the system should not return any of both (to be deterministic) so it should raise an exception. """ with app.app_context(): db.session.add(Tag(id='foo-bar')) org2 = Organization(name='org 2', tax_id='tax id org 2') db.session.add(Tag(id='foo-bar', org=org2)) db.session.commit() user.get(res=Tag, item='foo-bar/device', status=MultipleResourcesFound)