From 94c44e3480243dfbcf5bfb45d3f7a9c21b963e4c Mon Sep 17 00:00:00 2001 From: Xavier Bustamante Talavera Date: Thu, 4 Oct 2018 10:59:31 +0200 Subject: [PATCH] Add Smartphone; remove Inventory and use DeviceView --- ereuse_devicehub/config.py | 6 +- ereuse_devicehub/dummy/dummy.py | 15 +- .../dummy/files/smartphone.snapshot.yaml | 14 ++ ereuse_devicehub/resources/device/__init__.py | 146 ------------------ .../resources/device/definitions.py | 146 ++++++++++++++++++ ereuse_devicehub/resources/device/models.py | 2 +- ereuse_devicehub/resources/device/schemas.py | 17 +- ereuse_devicehub/resources/device/views.py | 70 ++++++++- ereuse_devicehub/resources/inventory.py | 125 --------------- ereuse_devicehub/resources/tag/__init__.py | 2 +- tests/files/smartphone.snapshot.yaml | 1 + tests/test_basic.py | 3 +- tests/test_device.py | 13 +- ...{test_inventory.py => test_device_find.py} | 76 ++++----- tests/test_snapshot.py | 5 + 15 files changed, 303 insertions(+), 338 deletions(-) create mode 100644 ereuse_devicehub/dummy/files/smartphone.snapshot.yaml create mode 100644 ereuse_devicehub/resources/device/definitions.py delete mode 100644 ereuse_devicehub/resources/inventory.py create mode 120000 tests/files/smartphone.snapshot.yaml rename tests/{test_inventory.py => test_device_find.py} (64%) diff --git a/ereuse_devicehub/config.py b/ereuse_devicehub/config.py index 936ed280..59879dbe 100644 --- a/ereuse_devicehub/config.py +++ b/ereuse_devicehub/config.py @@ -7,16 +7,16 @@ from teal.config import Config from teal.enums import Currency from teal.utils import import_resource -from ereuse_devicehub.resources import agent, device, event, inventory, lot, tag, user +from ereuse_devicehub.resources import agent, event, lot, tag, user +from ereuse_devicehub.resources.device import definitions from ereuse_devicehub.resources.enums import PriceSoftware, RatingSoftware class DevicehubConfig(Config): - RESOURCE_DEFINITIONS = set(chain(import_resource(device), + RESOURCE_DEFINITIONS = set(chain(import_resource(definitions), import_resource(event), import_resource(user), import_resource(tag), - import_resource(inventory), import_resource(agent), import_resource(lot))) PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str] diff --git a/ereuse_devicehub/dummy/dummy.py b/ereuse_devicehub/dummy/dummy.py index 94276a31..5ea4d91a 100644 --- a/ereuse_devicehub/dummy/dummy.py +++ b/ereuse_devicehub/dummy/dummy.py @@ -10,8 +10,8 @@ import yaml from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.resources.agent.models import Person +from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.event import models as m -from ereuse_devicehub.resources.inventory import Inventory from ereuse_devicehub.resources.lot.models import Lot from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.user import User @@ -102,14 +102,13 @@ class Dummy: assert len(lot['devices']) # Keep this at the bottom - inventory, _ = user.get(res=Inventory) - assert len(inventory['devices']) - assert len(inventory['lots']) + inventory, _ = user.get(res=Device) + assert len(inventory['items']) - i, _ = user.get(res=Inventory, query=[('search', 'intel')]) - assert len(i['devices']) == 10 - i, _ = user.get(res=Inventory, query=[('search', 'pc')]) - assert len(i['devices']) == 11 + i, _ = user.get(res=Device, query=[('search', 'intel')]) + assert len(i['items']) == 10 + i, _ = user.get(res=Device, query=[('search', 'pc')]) + assert len(i['items']) == 11 print('⭐ Done.') def user_client(self, email: str, password: str): diff --git a/ereuse_devicehub/dummy/files/smartphone.snapshot.yaml b/ereuse_devicehub/dummy/files/smartphone.snapshot.yaml new file mode 100644 index 00000000..10d378f1 --- /dev/null +++ b/ereuse_devicehub/dummy/files/smartphone.snapshot.yaml @@ -0,0 +1,14 @@ +type: Snapshot +software: Web +version: '1.0' +device: + type: Smartphone + manufacturer: Apple + model: A1586 + serialNumber: ABCDEF + imei: 35686800-004141-20 + events: + - type: AppRate + appearanceRange: A + functionalityRange: B + labelling: False diff --git a/ereuse_devicehub/resources/device/__init__.py b/ereuse_devicehub/resources/device/__init__.py index e888c988..e69de29b 100644 --- a/ereuse_devicehub/resources/device/__init__.py +++ b/ereuse_devicehub/resources/device/__init__.py @@ -1,146 +0,0 @@ -from typing import Callable, Iterable, Tuple - -from teal.resource import Converters, Resource - -from ereuse_devicehub.resources.device import schemas -from ereuse_devicehub.resources.device.models import Manufacturer -from ereuse_devicehub.resources.device.views import DeviceView, ManufacturerView - - -class DeviceDef(Resource): - SCHEMA = schemas.Device - VIEW = DeviceView - ID_CONVERTER = Converters.int - AUTH = False # We manage this at each view - - def __init__(self, app, - import_name=__name__, static_folder=None, - static_url_path=None, - template_folder='templates', - url_prefix=None, - subdomain=None, - url_defaults=None, - root_path=None, - cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()): - super().__init__(app, import_name, static_folder, static_url_path, template_folder, - url_prefix, subdomain, url_defaults, root_path, cli_commands) - - -class ComputerDef(DeviceDef): - VIEW = None - SCHEMA = schemas.Computer - - -class DesktopDef(ComputerDef): - VIEW = None - SCHEMA = schemas.Desktop - - -class LaptopDef(ComputerDef): - VIEW = None - SCHEMA = schemas.Laptop - - -class ServerDef(ComputerDef): - VIEW = None - SCHEMA = schemas.Server - - -class MonitorDef(DeviceDef): - VIEW = None - SCHEMA = schemas.Monitor - - -class ComputerMonitorDef(MonitorDef): - VIEW = None - SCHEMA = schemas.ComputerMonitor - - -class TelevisionSetDef(MonitorDef): - VIEW = None - SCHEMA = schemas.TelevisionSet - - -class MobileDef(DeviceDef): - VIEW = None - SCHEMA = schemas.Mobile - - -class SmartphoneDef(MobileDef): - VIEW = None - SCHEMA = schemas.Smartphone - - -class TabletDef(MobileDef): - VIEW = None - SCHEMA = schemas.Tablet - - -class CellphoneDef(MobileDef): - VIEW = None - SCHEMA = schemas.Cellphone - - -class ComponentDef(DeviceDef): - VIEW = None - SCHEMA = schemas.Component - - -class GraphicCardDef(ComponentDef): - VIEW = None - SCHEMA = schemas.GraphicCard - - -class DataStorageDef(ComponentDef): - VIEW = None - SCHEMA = schemas.DataStorage - - -class HardDriveDef(DataStorageDef): - VIEW = None - SCHEMA = schemas.HardDrive - - -class SolidStateDriveDef(DataStorageDef): - VIEW = None - SCHEMA = schemas.SolidStateDrive - - -class MotherboardDef(ComponentDef): - VIEW = None - SCHEMA = schemas.Motherboard - - -class NetworkAdapterDef(ComponentDef): - VIEW = None - SCHEMA = schemas.NetworkAdapter - - -class RamModuleDef(ComponentDef): - VIEW = None - SCHEMA = schemas.RamModule - - -class ProcessorDef(ComponentDef): - VIEW = None - SCHEMA = schemas.Processor - - -class SoundCardDef(ComponentDef): - VIEW = None - SCHEMA = schemas.SoundCard - - -class DisplayDef(ComponentDef): - VIEW = None - SCHEMA = schemas.Display - - -class ManufacturerDef(Resource): - VIEW = ManufacturerView - SCHEMA = schemas.Manufacturer - AUTH = True - - def init_db(self, db: 'db.SQLAlchemy'): - """Loads the manufacturers to the database.""" - Manufacturer.add_all_to_session(db.session) diff --git a/ereuse_devicehub/resources/device/definitions.py b/ereuse_devicehub/resources/device/definitions.py new file mode 100644 index 00000000..e888c988 --- /dev/null +++ b/ereuse_devicehub/resources/device/definitions.py @@ -0,0 +1,146 @@ +from typing import Callable, Iterable, Tuple + +from teal.resource import Converters, Resource + +from ereuse_devicehub.resources.device import schemas +from ereuse_devicehub.resources.device.models import Manufacturer +from ereuse_devicehub.resources.device.views import DeviceView, ManufacturerView + + +class DeviceDef(Resource): + SCHEMA = schemas.Device + VIEW = DeviceView + ID_CONVERTER = Converters.int + AUTH = False # We manage this at each view + + def __init__(self, app, + import_name=__name__, static_folder=None, + static_url_path=None, + template_folder='templates', + url_prefix=None, + subdomain=None, + url_defaults=None, + root_path=None, + cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()): + super().__init__(app, import_name, static_folder, static_url_path, template_folder, + url_prefix, subdomain, url_defaults, root_path, cli_commands) + + +class ComputerDef(DeviceDef): + VIEW = None + SCHEMA = schemas.Computer + + +class DesktopDef(ComputerDef): + VIEW = None + SCHEMA = schemas.Desktop + + +class LaptopDef(ComputerDef): + VIEW = None + SCHEMA = schemas.Laptop + + +class ServerDef(ComputerDef): + VIEW = None + SCHEMA = schemas.Server + + +class MonitorDef(DeviceDef): + VIEW = None + SCHEMA = schemas.Monitor + + +class ComputerMonitorDef(MonitorDef): + VIEW = None + SCHEMA = schemas.ComputerMonitor + + +class TelevisionSetDef(MonitorDef): + VIEW = None + SCHEMA = schemas.TelevisionSet + + +class MobileDef(DeviceDef): + VIEW = None + SCHEMA = schemas.Mobile + + +class SmartphoneDef(MobileDef): + VIEW = None + SCHEMA = schemas.Smartphone + + +class TabletDef(MobileDef): + VIEW = None + SCHEMA = schemas.Tablet + + +class CellphoneDef(MobileDef): + VIEW = None + SCHEMA = schemas.Cellphone + + +class ComponentDef(DeviceDef): + VIEW = None + SCHEMA = schemas.Component + + +class GraphicCardDef(ComponentDef): + VIEW = None + SCHEMA = schemas.GraphicCard + + +class DataStorageDef(ComponentDef): + VIEW = None + SCHEMA = schemas.DataStorage + + +class HardDriveDef(DataStorageDef): + VIEW = None + SCHEMA = schemas.HardDrive + + +class SolidStateDriveDef(DataStorageDef): + VIEW = None + SCHEMA = schemas.SolidStateDrive + + +class MotherboardDef(ComponentDef): + VIEW = None + SCHEMA = schemas.Motherboard + + +class NetworkAdapterDef(ComponentDef): + VIEW = None + SCHEMA = schemas.NetworkAdapter + + +class RamModuleDef(ComponentDef): + VIEW = None + SCHEMA = schemas.RamModule + + +class ProcessorDef(ComponentDef): + VIEW = None + SCHEMA = schemas.Processor + + +class SoundCardDef(ComponentDef): + VIEW = None + SCHEMA = schemas.SoundCard + + +class DisplayDef(ComponentDef): + VIEW = None + SCHEMA = schemas.Display + + +class ManufacturerDef(Resource): + VIEW = ManufacturerView + SCHEMA = schemas.Manufacturer + AUTH = True + + def init_db(self, db: 'db.SQLAlchemy'): + """Loads the manufacturers to the database.""" + Manufacturer.add_all_to_session(db.session) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index c8fd186b..03f1294a 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -241,7 +241,7 @@ class Mobile(Device): @validates('imei') def validate_imei(self, _, value: int): - if not imei.is_valid(value): + if not imei.is_valid(str(value)): raise ValidationError('{} is not a valid imei.'.format(value)) @validates('meid') diff --git a/ereuse_devicehub/resources/device/schemas.py b/ereuse_devicehub/resources/device/schemas.py index 221da8d4..c065285b 100644 --- a/ereuse_devicehub/resources/device/schemas.py +++ b/ereuse_devicehub/resources/device/schemas.py @@ -104,13 +104,18 @@ class TelevisionSet(Monitor): class Mobile(Device): - imei = Integer(validate=lambda x: imei.validate(str(x)), - description=m.Mobile.imei.comment) - meid = Str(validate=meid.validate, description=m.Mobile.meid.comment) + imei = Integer(description=m.Mobile.imei.comment) + meid = Str(description=m.Mobile.meid.comment) - @post_load - def convert_meid(self, data: dict): - if 'meid' in data: + @pre_load + def convert_check_imei(self, data): + if data.get('imei', None): + data['imei'] = int(imei.validate(data['imei'])) + return data + + @pre_load + def convert_check_meid(self, data: dict): + if data.get('meid', None): data['meid'] = meid.compact(data['meid']) diff --git a/ereuse_devicehub/resources/device/views.py b/ereuse_devicehub/resources/device/views.py index e6ae99ab..6528e8fe 100644 --- a/ereuse_devicehub/resources/device/views.py +++ b/ereuse_devicehub/resources/device/views.py @@ -4,14 +4,60 @@ import marshmallow from flask import current_app as app, render_template, request from flask.json import jsonify from flask_sqlalchemy import Pagination +from marshmallow import fields as f, validate as v +from teal import query from teal.cache import cache from teal.resource import View from ereuse_devicehub import auth +from ereuse_devicehub.db import db +from ereuse_devicehub.resources import search from ereuse_devicehub.resources.device.models import Device, Manufacturer +from ereuse_devicehub.resources.device.search import DeviceSearch +from ereuse_devicehub.resources.event.models import Rate +from ereuse_devicehub.resources.tag.model import Tag + + +class OfType(f.Str): + def __init__(self, column: db.Column, *args, **kwargs): + super().__init__(*args, **kwargs) + self.column = column + + def _deserialize(self, value, attr, data): + v = super()._deserialize(value, attr, data) + return self.column.in_(app.resources[v].subresources_types) + + +class RateQ(query.Query): + rating = query.Between(Rate.rating, f.Float()) + appearance = query.Between(Rate.appearance, f.Float()) + functionality = query.Between(Rate.functionality, f.Float()) + + +class TagQ(query.Query): + id = query.Or(query.ILike(Tag.id), required=True) + org = query.ILike(Tag.org) + + +class Filters(query.Query): + type = query.Or(OfType(Device.type)) + model = query.ILike(Device.model) + manufacturer = query.ILike(Device.manufacturer) + serialNumber = query.ILike(Device.serial_number) + rating = query.Join(Device.id == Rate.device_id, RateQ) + tag = query.Join(Device.id == Tag.id, TagQ) + + +class Sorting(query.Sort): + created = query.SortField(Device.created) class DeviceView(View): + class FindArgs(marshmallow.Schema): + search = f.Str() + filter = f.Nested(Filters, missing=[]) + sort = f.Nested(Sorting, missing=[]) + page = f.Integer(validate=v.Range(min=1), missing=1) def get(self, id): """ @@ -48,7 +94,29 @@ class DeviceView(View): @auth.Auth.requires_auth def find(self, args: dict): """Gets many devices.""" - return self.schema.jsonify(Device.query, many=True) + search_p = args.get('search', None) + query = Device.query + if search_p: + properties = DeviceSearch.properties + tags = DeviceSearch.tags + query = query.join(DeviceSearch).filter( + search.Search.match(properties, search_p) | search.Search.match(tags, search_p) + ).order_by( + search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p) + ) + query = query.filter(*args['filter']).order_by(*args['sort']) + devices = query.paginate(page=args['page'], per_page=30) # type: Pagination + ret = { + 'items': self.schema.dump(devices.items, many=True, nested=1), + # todo pagination should be in Header like github + # https://developer.github.com/v3/guides/traversing-with-pagination/ + 'pagination': { + 'page': devices.page, + 'perPage': devices.per_page, + 'total': devices.total + } + } + return jsonify(ret) class ManufacturerView(View): diff --git a/ereuse_devicehub/resources/inventory.py b/ereuse_devicehub/resources/inventory.py deleted file mode 100644 index de94e281..00000000 --- a/ereuse_devicehub/resources/inventory.py +++ /dev/null @@ -1,125 +0,0 @@ -from flask import current_app as app, jsonify -from flask_sqlalchemy import Pagination -from marshmallow import Schema as MarshmallowSchema -from marshmallow.fields import Float, Integer, Nested, Str -from marshmallow.validate import Range -from sqlalchemy import Column -from teal.query import Between, ILike, Join, Or, Query, Sort, SortField -from teal.resource import Resource, View - -from ereuse_devicehub.resources import search -from ereuse_devicehub.resources.device.models import Device -from ereuse_devicehub.resources.device.search import DeviceSearch -from ereuse_devicehub.resources.event.models import Rate -from ereuse_devicehub.resources.lot.models import Lot -from ereuse_devicehub.resources.schemas import Thing -from ereuse_devicehub.resources.tag import Tag - - -class Inventory(Thing): - pass - - -class RateQ(Query): - rating = Between(Rate.rating, Float()) - appearance = Between(Rate.appearance, Float()) - functionality = Between(Rate.functionality, Float()) - - -class TagQ(Query): - id = Or(ILike(Tag.id), required=True) - org = ILike(Tag.org) - - -class OfType(Str): - def __init__(self, column: Column, *args, **kwargs): - super().__init__(*args, **kwargs) - self.column = column - - def _deserialize(self, value, attr, data): - v = super()._deserialize(value, attr, data) - return self.column.in_(app.resources[v].subresources_types) - - -class Filters(Query): - type = Or(OfType(Device.type)) - model = ILike(Device.model) - manufacturer = ILike(Device.manufacturer) - serialNumber = ILike(Device.serial_number) - rating = Join(Device.id == Rate.device_id, RateQ) - tag = Join(Device.id == Tag.id, TagQ) - - -class Sorting(Sort): - created = SortField(Device.created) - - -class InventoryView(View): - class FindArgs(MarshmallowSchema): - search = Str() - filter = Nested(Filters, missing=[]) - sort = Nested(Sorting, missing=[Device.created.desc()]) - page = Integer(validate=Range(min=1), missing=1) - - def get(self, id): - """Inventory view - --- - description: Supports the inventory view of ``devicehub-client``; returns - all the devices, groups and widgets of this Devicehub instance. - responses: - 200: - description: The inventory. - schema: - type: object - properties: - devices: - type: array - items: - $ref: '#/definitions/Device' - pagination: - type: object - properties: - page: - type: integer - minimum: 0 - perPage: - type: integer - minimum: 0 - total: - type: integer - minimum: 0 - """ - # todo .format(yaml.load(schema2parameters(self.FindArgs, default_in='path', name='path'))) - return super().get(id) - - def find(self, args: dict): - """See :meth:`.get` above.""" - search_p = args.get('search', None) - query = Device.query - if search_p: - properties = DeviceSearch.properties - tags = DeviceSearch.tags - query = query.join(DeviceSearch).filter( - search.Search.match(properties, search_p) | search.Search.match(tags, search_p) - ).order_by( - search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p) - ) - query = query.filter(*args['filter']).order_by(*args['sort']) - devices = query.paginate(page=args['page'], per_page=30) # type: Pagination - inventory = { - 'devices': app.resources[Device.t].schema.dump(devices.items, many=True, nested=1), - 'lots': app.resources[Lot.t].schema.dump(Lot.roots(), many=True, nested=1), - 'widgets': {}, - 'pagination': { - 'page': devices.page, - 'perPage': devices.per_page, - 'total': devices.total, - } - } - return jsonify(inventory) - - -class InventoryDef(Resource): - SCHEMA = Inventory - VIEW = InventoryView - AUTH = True diff --git a/ereuse_devicehub/resources/tag/__init__.py b/ereuse_devicehub/resources/tag/__init__.py index 8a01852f..db1e2752 100644 --- a/ereuse_devicehub/resources/tag/__init__.py +++ b/ereuse_devicehub/resources/tag/__init__.py @@ -7,7 +7,7 @@ from teal.resource import Converters, Resource from teal.teal import Teal from ereuse_devicehub.db import db -from ereuse_devicehub.resources.device import DeviceDef +from ereuse_devicehub.resources.device.definitions import DeviceDef from ereuse_devicehub.resources.tag import schema from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.tag.view import TagDeviceView, TagView, get_device_from_tag diff --git a/tests/files/smartphone.snapshot.yaml b/tests/files/smartphone.snapshot.yaml new file mode 120000 index 00000000..390a914c --- /dev/null +++ b/tests/files/smartphone.snapshot.yaml @@ -0,0 +1 @@ +../../ereuse_devicehub/dummy/files/smartphone.snapshot.yaml \ No newline at end of file diff --git a/tests/test_basic.py b/tests/test_basic.py index 3b9d49b7..c1e7ee28 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -17,7 +17,6 @@ def test_api_docs(client: Client): docs, _ = client.get('/apidocs') assert set(docs['paths'].keys()) == { # todo this does not appear: '/tags/{id}/device', - '/inventories/', '/apidocs', '/users/', '/devices/', @@ -40,4 +39,4 @@ def test_api_docs(client: Client): 'scheme': 'basic', 'name': 'Authorization' } - assert 78 == len(docs['definitions']) + assert 77 == len(docs['definitions']) diff --git a/tests/test_device.py b/tests/test_device.py index 2ce2d6dd..e7608fa5 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -24,7 +24,6 @@ from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, Mismatch from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.event.models import Remove, Test -from ereuse_devicehub.resources.inventory import Inventory from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.user import User from tests import conftest @@ -423,8 +422,8 @@ def test_get_devices(app: Devicehub, user: UserClient): db.session.add_all((pc, pc1, pc2)) db.session.commit() devices, _ = user.get(res=Device) - assert tuple(d['id'] for d in devices) == (1, 2, 3, 4, 5) - assert tuple(d['type'] for d in devices) == ( + assert tuple(d['id'] for d in devices['items']) == (1, 2, 3, 4, 5) + assert tuple(d['type'] for d in devices['items']) == ( 'Desktop', 'Desktop', 'Laptop', 'NetworkAdapter', 'GraphicCard' ) @@ -463,12 +462,12 @@ def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClie with app.app_context(): app.db.session.execute('TRUNCATE TABLE {}'.format(DeviceSearch.__table__.name)) app.db.session.commit() - i, _ = user.get(res=Inventory, query=[('search', 'Desktop')]) - assert not len(i['devices']) + i, _ = user.get(res=Device, query=[('search', 'Desktop')]) + assert not len(i['items']) with app.app_context(): DeviceSearch.set_all_devices_tokens_if_empty(app.db.session) - i, _ = user.get(res=Inventory, query=[('search', 'Desktop')]) - assert not len(i['devices']) + i, _ = user.get(res=Device, query=[('search', 'Desktop')]) + assert not len(i['items']) def test_manufacturer(user: UserClient): diff --git a/tests/test_inventory.py b/tests/test_device_find.py similarity index 64% rename from tests/test_inventory.py rename to tests/test_device_find.py index 6eb4c40b..b53853b1 100644 --- a/tests/test_inventory.py +++ b/tests/test_device_find.py @@ -5,15 +5,15 @@ from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub from ereuse_devicehub.resources.device.models import Desktop, Device, Laptop, SolidStateDrive +from ereuse_devicehub.resources.device.views import Filters, Sorting from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.event.models import Snapshot -from ereuse_devicehub.resources.inventory import Filters, Inventory, Sorting from tests import conftest from tests.conftest import file @pytest.mark.usefixtures(conftest.app_context.__name__) -def test_inventory_filters(): +def test_device_filters(): schema = Filters() q = schema.load({ 'type': ['Computer', 'Laptop'], @@ -45,14 +45,14 @@ def test_inventory_filters(): @pytest.mark.usefixtures(conftest.app_context.__name__) -def test_inventory_sort(): +def test_device_sort(): schema = Sorting() r = next(schema.load({'created': True})) assert str(r) == 'device.created ASC' @pytest.fixture() -def inventory_query_dummy(app: Devicehub): +def device_query_dummy(app: Devicehub): with app.app_context(): devices = ( # The order matters ;-) Desktop(serial_number='s1', @@ -75,72 +75,72 @@ def inventory_query_dummy(app: Devicehub): db.session.commit() -@pytest.mark.usefixtures(inventory_query_dummy.__name__) -def test_inventory_query_no_filters(user: UserClient): - i, _ = user.get(res=Inventory) - assert tuple(d['type'] for d in i['devices']) == ( - 'SolidStateDrive', 'Desktop', 'Laptop', 'Desktop' +@pytest.mark.usefixtures(device_query_dummy.__name__) +def test_device_query_no_filters(user: UserClient): + i, _ = user.get(res=Device) + assert tuple(d['type'] for d in i['items']) == ( + 'Desktop', 'Laptop', 'Desktop', 'SolidStateDrive' ) -@pytest.mark.usefixtures(inventory_query_dummy.__name__) -def test_inventory_query_filter_type(user: UserClient): - i, _ = user.get(res=Inventory, query=[('filter', {'type': ['Desktop', 'Laptop']})]) - assert tuple(d['type'] for d in i['devices']) == ('Desktop', 'Laptop', 'Desktop') +@pytest.mark.usefixtures(device_query_dummy.__name__) +def test_device_query_filter_type(user: UserClient): + i, _ = user.get(res=Device, query=[('filter', {'type': ['Desktop', 'Laptop']})]) + assert tuple(d['type'] for d in i['items']) == ('Desktop', 'Laptop', 'Desktop') -@pytest.mark.usefixtures(inventory_query_dummy.__name__) -def test_inventory_query_filter_sort(user: UserClient): - i, _ = user.get(res=Inventory, query=[ +@pytest.mark.usefixtures(device_query_dummy.__name__) +def test_device_query_filter_sort(user: UserClient): + i, _ = user.get(res=Device, query=[ ('sort', {'created': Sorting.ASCENDING}), ('filter', {'type': ['Computer']}) ]) - assert tuple(d['type'] for d in i['devices']) == ('Desktop', 'Laptop', 'Desktop') + assert tuple(d['type'] for d in i['items']) == ('Desktop', 'Laptop', 'Desktop') -def test_inventory_query(user: UserClient): +def test_device_query(user: UserClient): """Checks result of inventory.""" user.post(conftest.file('basic.snapshot'), res=Snapshot) - i, _ = user.get(res=Inventory) - pc = next(d for d in i['devices'] if d['type'] == 'Desktop') + i, _ = user.get(res=Device) + pc = next(d for d in i['items'] if d['type'] == 'Desktop') assert len(pc['events']) == 4 assert len(pc['components']) == 3 assert not pc['tags'] @pytest.mark.xfail(reason='Functionality not yet developed.') -def test_inventory_lots_query(user: UserClient): +def test_device_lots_query(user: UserClient): pass -def test_inventory_query_search(user: UserClient): +def test_device_query_search(user: UserClient): # todo improve user.post(file('basic.snapshot'), res=Snapshot) user.post(file('computer-monitor.snapshot'), res=Snapshot) user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot) - i, _ = user.get(res=Inventory, query=[('search', 'desktop')]) - assert i['devices'][0]['id'] == 1 - i, _ = user.get(res=Inventory, query=[('search', 'intel')]) - assert len(i['devices']) == 1 + i, _ = user.get(res=Device, query=[('search', 'desktop')]) + assert i['items'][0]['id'] == 1 + i, _ = user.get(res=Device, query=[('search', 'intel')]) + assert len(i['items']) == 1 @pytest.mark.xfail(reason='No dictionary yet that knows asustek = asus') -def test_inventory_query_search_synonyms_asus(user: UserClient): +def test_device_query_search_synonyms_asus(user: UserClient): user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot) - i, _ = user.get(res=Inventory, query=[('search', 'asustek')]) - assert len(i['devices']) == 1 - i, _ = user.get(res=Inventory, query=[('search', 'asus')]) - assert len(i['devices']) == 1 + i, _ = user.get(res=Device, query=[('search', 'asustek')]) + assert len(i['items']) == 1 + i, _ = user.get(res=Device, query=[('search', 'asus')]) + assert len(i['items']) == 1 @pytest.mark.xfail(reason='No dictionary yet that knows hp = hewlett packard') -def test_inventory_query_search_synonyms_intel(user: UserClient): +def test_device_query_search_synonyms_intel(user: UserClient): s = file('real-hp.snapshot.11') s['device']['model'] = 'foo' # The model had the word 'HP' in it user.post(s, res=Snapshot) - i, _ = user.get(res=Inventory, query=[('search', 'hewlett packard')]) - assert len(i['devices']) == 1 - i, _ = user.get(res=Inventory, query=[('search', 'hewlett')]) - assert len(i['devices']) == 1 - i, _ = user.get(res=Inventory, query=[('search', 'hp')]) - assert len(i['devices']) == 1 + i, _ = user.get(res=Device, query=[('search', 'hewlett packard')]) + assert len(i['items']) == 1 + i, _ = user.get(res=Device, query=[('search', 'hewlett')]) + assert len(i['items']) == 1 + i, _ = user.get(res=Device, query=[('search', 'hp')]) + assert len(i['items']) == 1 diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 8acf78c0..54c23b47 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -328,6 +328,11 @@ def test_snapshot_computer_monitor(user: UserClient): snapshot_and_check(user, s, event_types=('AppRate',)) +def test_snapshot_mobile_smartphone(user: UserClient): + s = file('smartphone.snapshot') + snapshot_and_check(user, s, event_types=('AppRate',)) + + def test_snapshot_components_none(): """ Tests that a snapshot without components does not