Add Smartphone; remove Inventory and use DeviceView
This commit is contained in:
parent
3bd4168174
commit
94c44e3480
|
@ -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]
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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')
|
||||
|
|
|
@ -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'])
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../../ereuse_devicehub/dummy/files/smartphone.snapshot.yaml
|
|
@ -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'])
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Reference in New Issue