Merge remote-tracking branch 'origin/master' into reports
This commit is contained in:
commit
cad0b64125
|
@ -17,6 +17,12 @@
|
|||
"elapsed": 19,
|
||||
"rate": 19.3106,
|
||||
"type": "BenchmarkRamSysbench"
|
||||
},
|
||||
{
|
||||
"appearanceRange": "A",
|
||||
"biosRange": "A",
|
||||
"functionalityRange": "A",
|
||||
"type": "WorkbenchRate"
|
||||
}
|
||||
],
|
||||
"manufacturer": "ASUSTeK Computer INC."
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
"error": false,
|
||||
"type": "StressTest",
|
||||
"elapsed": 60
|
||||
},
|
||||
{
|
||||
"appearanceRange": "A",
|
||||
"biosRange": "A",
|
||||
"functionalityRange": "A",
|
||||
"type": "WorkbenchRate"
|
||||
}
|
||||
],
|
||||
"type": "Desktop",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
type: Snapshot
|
||||
version: '1.0'
|
||||
software: Web
|
||||
device:
|
||||
type: Keyboard
|
||||
model: FOO
|
||||
serialNumber: BAR
|
||||
manufacturer: BAZ
|
||||
layout: ES
|
||||
events:
|
||||
- type: ManualRate
|
||||
appearanceRange: A
|
||||
functionalityRange: A
|
||||
labelling: False
|
|
@ -14,6 +14,12 @@
|
|||
"rate": 0.9323,
|
||||
"elapsed": 1,
|
||||
"type": "BenchmarkRamSysbench"
|
||||
},
|
||||
{
|
||||
"appearanceRange": "B",
|
||||
"biosRange": "A",
|
||||
"functionalityRange": "C",
|
||||
"type": "WorkbenchRate"
|
||||
}
|
||||
],
|
||||
"type": "Desktop",
|
||||
|
|
|
@ -145,6 +145,12 @@
|
|||
"type": "StressTest",
|
||||
"error": false,
|
||||
"elapsed": 60
|
||||
},
|
||||
{
|
||||
"appearanceRange": "B",
|
||||
"biosRange": "C",
|
||||
"functionalityRange": "A",
|
||||
"type": "WorkbenchRate"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -148,6 +148,12 @@
|
|||
"rate": 0.9759,
|
||||
"type": "BenchmarkRamSysbench",
|
||||
"elapsed": 1
|
||||
},
|
||||
{
|
||||
"appearanceRange": "B",
|
||||
"biosRange": "A",
|
||||
"functionalityRange": "D",
|
||||
"type": "WorkbenchRate"
|
||||
}
|
||||
],
|
||||
"serialNumber": "CZC0408YJG",
|
||||
|
|
|
@ -161,6 +161,121 @@ class DisplayDef(ComponentDef):
|
|||
SCHEMA = schemas.Display
|
||||
|
||||
|
||||
class ComputerAccessoryDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.ComputerAccessory
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, 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 MouseDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Mouse
|
||||
|
||||
|
||||
class KeyboardDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Keyboard
|
||||
|
||||
|
||||
class SAIDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.SAI
|
||||
|
||||
|
||||
class MemoryCardReaderDef(ComputerAccessoryDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.MemoryCardReader
|
||||
|
||||
|
||||
class NetworkingDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Networking
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, 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 RouterDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Router
|
||||
|
||||
|
||||
class SwitchDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Switch
|
||||
|
||||
|
||||
class HubDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Hub
|
||||
|
||||
|
||||
class WirelessAccessPointDef(NetworkingDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.WirelessAccessPoint
|
||||
|
||||
|
||||
class PrinterDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Printer
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, 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 LabelPrinterDef(PrinterDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.LabelPrinter
|
||||
|
||||
|
||||
class SoundDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Sound
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, 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 MicrophoneDef(SoundDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Microphone
|
||||
|
||||
|
||||
class VideoDef(DeviceDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Video
|
||||
|
||||
def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
|
||||
template_folder=None, 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 VideoScalerDef(VideoDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.VideoScaler
|
||||
|
||||
|
||||
class VideoconferenceDef(VideoDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Videoconference
|
||||
|
||||
|
||||
class ManufacturerDef(Resource):
|
||||
VIEW = ManufacturerView
|
||||
SCHEMA = schemas.Manufacturer
|
||||
|
|
|
@ -17,12 +17,13 @@ from sqlalchemy_utils import ColorType
|
|||
from stdnum import imei, meid
|
||||
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, URL, check_lower, \
|
||||
check_range
|
||||
from teal.enums import Layouts
|
||||
from teal.marshmallow import ValidationError
|
||||
from teal.resource import url_for_resource
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, \
|
||||
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing
|
||||
|
||||
|
||||
|
@ -62,6 +63,19 @@ class Device(Thing):
|
|||
"""
|
||||
color = Column(ColorType)
|
||||
color.comment = """The predominant color of the device."""
|
||||
production_date = Column(db.TIMESTAMP(timezone=True))
|
||||
production_date.comment = """The date of production of the item."""
|
||||
|
||||
_NON_PHYSICAL_PROPS = {
|
||||
'id',
|
||||
'type',
|
||||
'created',
|
||||
'updated',
|
||||
'parent_id',
|
||||
'hid',
|
||||
'production_date',
|
||||
'color'
|
||||
}
|
||||
|
||||
@property
|
||||
def events(self) -> list:
|
||||
|
@ -94,7 +108,7 @@ class Device(Thing):
|
|||
for c in inspect(self.__class__).attrs
|
||||
if isinstance(c, ColumnProperty)
|
||||
and not getattr(c, 'foreign_keys', None)
|
||||
and c.key not in {'id', 'type', 'created', 'updated', 'parent_id', 'hid'}}
|
||||
and c.key not in self._NON_PHYSICAL_PROPS}
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
|
@ -194,6 +208,11 @@ class Device(Thing):
|
|||
|
||||
|
||||
class DisplayMixin:
|
||||
"""
|
||||
Aspect ratio can be computed as in
|
||||
https://github.com/mirukan/whratio/blob/master/whratio/ratio.py and
|
||||
could be a future property.
|
||||
"""
|
||||
size = Column(Float(decimal_return_scale=2), check_range('size', 2, 150))
|
||||
size.comment = """
|
||||
The size of the monitor in inches.
|
||||
|
@ -212,6 +231,10 @@ class DisplayMixin:
|
|||
The maximum vertical resolution the monitor can natively support
|
||||
in pixels.
|
||||
"""
|
||||
refresh_rate = Column(SmallInteger, check_range('refresh_rate', 10, 1000))
|
||||
contrast_ratio = Column(SmallInteger, check_range('contrast_ratio', 100, 100000))
|
||||
touchable = Column(Boolean, nullable=False, default=False)
|
||||
touchable.comment = """Whether it is a touchscreen."""
|
||||
|
||||
def __format__(self, format_spec: str) -> str:
|
||||
v = ''
|
||||
|
@ -226,6 +249,10 @@ class Computer(Device):
|
|||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
chassis = Column(DBEnum(ComputerChassis), nullable=False)
|
||||
|
||||
def __init__(self, chassis, **kwargs) -> None:
|
||||
chassis = ComputerChassis(chassis)
|
||||
super().__init__(chassis=chassis, **kwargs)
|
||||
|
||||
@property
|
||||
def events(self) -> list:
|
||||
return sorted(chain(super().events, self.events_parent), key=attrgetter('created'))
|
||||
|
@ -285,7 +312,9 @@ class Desktop(Computer):
|
|||
|
||||
|
||||
class Laptop(Computer):
|
||||
pass
|
||||
layout = Column(DBEnum(Layouts))
|
||||
layout.comment = """Layout of a built-in keyboard of the computer,
|
||||
if any."""
|
||||
|
||||
|
||||
class Server(Computer):
|
||||
|
@ -304,6 +333,10 @@ class TelevisionSet(Monitor):
|
|||
pass
|
||||
|
||||
|
||||
class Projector(Monitor):
|
||||
pass
|
||||
|
||||
|
||||
class Mobile(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
imei = Column(BigInteger)
|
||||
|
@ -479,6 +512,83 @@ class Display(JoinedComponentTableMixin, DisplayMixin, Component):
|
|||
pass
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = Column(DBEnum(Layouts)) # If we want to do it not null
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
id = Column(BigInteger, ForeignKey(Device.id), primary_key=True)
|
||||
wireless = Column(Boolean, nullable=False, default=False)
|
||||
wireless.comment = """Whether it is a wireless printer."""
|
||||
scanning = Column(Boolean, nullable=False, default=False)
|
||||
scanning.comment = """Whether the printer has scanning capabilities."""
|
||||
technology = Column(DBEnum(PrinterTechnology))
|
||||
technology.comment = """Technology used to print."""
|
||||
monochrome = Column(Boolean, nullable=False, default=True)
|
||||
monochrome.comment = """Whether the printer is only monochrome."""
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(db.Model):
|
||||
__table_args__ = {'schema': 'common'}
|
||||
CSV_DELIMITER = csv.get_dialect('excel').delimiter
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from datetime import datetime
|
||||
from typing import Dict, List, Set, Type, Union
|
||||
|
||||
from boltons import urlutils
|
||||
|
@ -6,11 +7,12 @@ from colour import Color
|
|||
from sqlalchemy import Column, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
from teal.db import Model
|
||||
from teal.enums import Layouts
|
||||
|
||||
from ereuse_devicehub.resources.agent.models import Agent
|
||||
from ereuse_devicehub.resources.device import states
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, \
|
||||
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.event import models as e
|
||||
from ereuse_devicehub.resources.image.models import ImageList
|
||||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
|
@ -31,6 +33,7 @@ class Device(Thing):
|
|||
depth = ... # type: Column
|
||||
color = ... # type: Column
|
||||
lots = ... # type: relationship
|
||||
production_date = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
@ -52,6 +55,7 @@ class Device(Thing):
|
|||
self.images = ... # type: ImageList
|
||||
self.tags = ... # type: Set[Tag]
|
||||
self.lots = ... # type: Set[Lot]
|
||||
self.production_date = ... # type: datetime
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
|
@ -86,6 +90,9 @@ class DisplayMixin:
|
|||
size = ... # type: Column
|
||||
resolution_width = ... # type: Column
|
||||
resolution_height = ... # type: Column
|
||||
refresh_rate = ... # type: Column
|
||||
contrast_ratio = ... # type: Column
|
||||
touchable = ... # type: Column
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
@ -93,6 +100,9 @@ class DisplayMixin:
|
|||
self.size = ... # type: Integer
|
||||
self.resolution_width = ... # type: int
|
||||
self.resolution_height = ... # type: int
|
||||
self.refresh_rate = ... # type: int
|
||||
self.contrast_ratio = ... # type: int
|
||||
self.touchable = ... # type: bool
|
||||
|
||||
|
||||
class Computer(DisplayMixin, Device):
|
||||
|
@ -135,7 +145,11 @@ class Desktop(Computer):
|
|||
|
||||
|
||||
class Laptop(Computer):
|
||||
pass
|
||||
layout = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.layout = ... # type: Layouts
|
||||
|
||||
|
||||
class Server(Computer):
|
||||
|
@ -233,12 +247,18 @@ class Motherboard(Component):
|
|||
self.pcmcia = ... # type: int
|
||||
|
||||
|
||||
class NetworkAdapter(Component):
|
||||
class NetworkMixin:
|
||||
speed = ... # type: Column
|
||||
wireless = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.speed = ... # type: int
|
||||
self.wireless = ... # type: bool
|
||||
|
||||
|
||||
class NetworkAdapter(NetworkMixin, Component):
|
||||
pass
|
||||
|
||||
|
||||
class Processor(Component):
|
||||
|
@ -271,6 +291,88 @@ class Display(DisplayMixin, Component):
|
|||
pass
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = ... # type: Column
|
||||
|
||||
def __init__(self, layout: Layouts, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.layout = ... # type: Layouts
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
pass
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
wireless = ... # type: Column
|
||||
scanning = ... # type: Column
|
||||
technology = ... # type: Column
|
||||
monochrome = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.wireless = ... # type: bool
|
||||
self.scanning = ... # type: bool
|
||||
self.technology = ... # type: PrinterTechnology
|
||||
self.monochrome = ... # type: bool
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(Model):
|
||||
CUSTOM_MANUFACTURERS = ... # type: set
|
||||
name = ... # type: Column
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
from marshmallow import post_load, pre_load
|
||||
from marshmallow.fields import Boolean, Float, Integer, List, Str, String
|
||||
from marshmallow.fields import Boolean, DateTime, Float, Integer, List, Str, String
|
||||
from marshmallow.validate import Length, OneOf, Range
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from stdnum import imei, meid
|
||||
from teal.enums import Layouts
|
||||
from teal.marshmallow import EnumField, SanitizedStr, URL, ValidationError
|
||||
from teal.resource import Schema
|
||||
|
||||
from ereuse_devicehub.marshmallow import NestedOn
|
||||
from ereuse_devicehub.resources.device import models as m, states
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, \
|
||||
DataStoragePrivacyCompliance, DisplayTech, RamFormat, RamInterface
|
||||
DataStoragePrivacyCompliance, DisplayTech, PrinterTechnology, RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
|
||||
from ereuse_devicehub.resources.schemas import Thing, UnitCodes
|
||||
|
||||
|
@ -40,6 +41,9 @@ class Device(Thing):
|
|||
trading = EnumField(states.Trading, dump_only=True, description=m.Device.trading.__doc__)
|
||||
physical = EnumField(states.Physical, dump_only=True, description=m.Device.physical.__doc__)
|
||||
physical_possessor = NestedOn('Agent', dump_only=True, data_key='physicalPossessor')
|
||||
production_date = DateTime('iso',
|
||||
description=m.Device.updated.comment,
|
||||
data_key='productionDate')
|
||||
|
||||
@pre_load
|
||||
def from_events_to_events_one(self, data: dict):
|
||||
|
@ -98,6 +102,9 @@ class DisplayMixin:
|
|||
resolution_height = Integer(data_key='resolutionHeight',
|
||||
validate=Range(10, 20000),
|
||||
description=m.DisplayMixin.resolution_height.comment)
|
||||
refresh_rate = Integer(data_key='refreshRate', validate=Range(10, 1000))
|
||||
contrast_ratio = Integer(data_key='contrastRatio', validate=Range(100, 100000))
|
||||
touchable = Boolean(missing=False, description=m.DisplayMixin.touchable.comment)
|
||||
|
||||
|
||||
class NetworkMixin:
|
||||
|
@ -212,3 +219,74 @@ class Manufacturer(Schema):
|
|||
name = String(dump_only=True)
|
||||
url = URL(dump_only=True)
|
||||
logo = URL(dump_only=True)
|
||||
|
||||
|
||||
class ComputerAccessory(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Mouse(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class MemoryCardReader(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class SAI(ComputerAccessory):
|
||||
pass
|
||||
|
||||
|
||||
class Keyboard(ComputerAccessory):
|
||||
layout = EnumField(Layouts)
|
||||
|
||||
|
||||
class Networking(NetworkMixin, Device):
|
||||
pass
|
||||
|
||||
|
||||
class Router(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Switch(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Hub(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class WirelessAccessPoint(Networking):
|
||||
pass
|
||||
|
||||
|
||||
class Printer(Device):
|
||||
wireless = Boolean(required=True, missing=False)
|
||||
scanning = Boolean(required=True, missing=False)
|
||||
technology = EnumField(PrinterTechnology, required=True)
|
||||
monochrome = Boolean(required=True, missing=True)
|
||||
|
||||
|
||||
class LabelPrinter(Printer):
|
||||
pass
|
||||
|
||||
|
||||
class Sound(Device):
|
||||
pass
|
||||
|
||||
|
||||
class Microphone(Sound):
|
||||
pass
|
||||
|
||||
|
||||
class Video(Device):
|
||||
pass
|
||||
|
||||
|
||||
class VideoScaler(Video):
|
||||
pass
|
||||
|
||||
|
||||
class Videoconference(Video):
|
||||
pass
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from itertools import chain
|
||||
|
||||
import inflection
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.dialects.postgresql import TSVECTOR
|
||||
|
@ -37,21 +39,24 @@ class DeviceSearch(db.Model):
|
|||
|
||||
@classmethod
|
||||
def update_modified_devices(cls, session: db.Session):
|
||||
"""Updates the documents of the devices that are part of a modified
|
||||
event in the passed-in session.
|
||||
"""Updates the documents of the devices that are part of a
|
||||
modified event, or tag in the passed-in session.
|
||||
|
||||
This method is registered as a SQLAlchemy
|
||||
listener in the Devicehub class.
|
||||
This method is registered as a SQLAlchemy listener in the
|
||||
Devicehub class.
|
||||
"""
|
||||
devices_to_update = set()
|
||||
for event in (e for e in session.new if isinstance(e, Event)):
|
||||
if isinstance(event, EventWithMultipleDevices):
|
||||
devices_to_update |= event.devices
|
||||
elif isinstance(event, EventWithOneDevice):
|
||||
devices_to_update.add(event.device)
|
||||
if event.parent:
|
||||
devices_to_update.add(event.parent)
|
||||
devices_to_update |= event.components
|
||||
for model in chain(session.new, session.dirty):
|
||||
if isinstance(model, Event):
|
||||
if isinstance(model, EventWithMultipleDevices):
|
||||
devices_to_update |= model.devices
|
||||
elif isinstance(model, EventWithOneDevice):
|
||||
devices_to_update.add(model.device)
|
||||
if model.parent:
|
||||
devices_to_update.add(model.parent)
|
||||
devices_to_update |= model.components
|
||||
elif isinstance(model, Tag) and model.device:
|
||||
devices_to_update.add(model.device)
|
||||
|
||||
# this flush is controversial:
|
||||
# see https://groups.google.com/forum/#!topic/sqlalchemy/hBzfypgPfYo
|
||||
|
|
|
@ -229,7 +229,7 @@ class Sync:
|
|||
if adding:
|
||||
# For the components we are adding, let's remove them from their old parents
|
||||
def g_parent(component: Component) -> Device:
|
||||
return component.parent or Computer(id=0) # Computer with id 0 is our Identity
|
||||
return component.parent or Device(id=0) # Computer with id 0 is our Identity
|
||||
|
||||
for parent, _components in groupby(sorted(adding, key=g_parent), key=g_parent):
|
||||
if parent.id != 0: # Is not Computer Identity
|
||||
|
|
|
@ -234,15 +234,15 @@ class DeviceRow(OrderedDict):
|
|||
|
||||
class ManufacturerView(View):
|
||||
class FindArgs(marshmallow.Schema):
|
||||
name = marshmallow.fields.Str(required=True,
|
||||
# Disallow like operators
|
||||
validate=lambda x: '%' not in x and '_' not in x)
|
||||
search = marshmallow.fields.Str(required=True,
|
||||
# Disallow like operators
|
||||
validate=lambda x: '%' not in x and '_' not in x)
|
||||
|
||||
@cache(datetime.timedelta(days=1))
|
||||
def find(self, args: dict):
|
||||
name = args['name']
|
||||
search = args['search']
|
||||
manufacturers = Manufacturer.query \
|
||||
.filter(Manufacturer.name.ilike(name + '%')) \
|
||||
.filter(Manufacturer.name.ilike(search + '%')) \
|
||||
.paginate(page=1, per_page=6) # type: Pagination
|
||||
return jsonify(
|
||||
items=app.resources[Manufacturer.t].schema.dump(
|
||||
|
|
|
@ -276,3 +276,12 @@ class DataStoragePrivacyCompliance(Enum):
|
|||
return cls.EraseSectors if not erasure.error else cls.EraseSectorsError
|
||||
else:
|
||||
return cls.EraseBasic if not erasure.error else cls.EraseBasicError
|
||||
|
||||
|
||||
class PrinterTechnology(Enum):
|
||||
"""Technology of the printer."""
|
||||
Toner = 'Toner / Laser'
|
||||
Inkjet = 'Liquid inkjet'
|
||||
SolidInk = 'Solid ink'
|
||||
Dye = 'Dye-sublimation'
|
||||
Thermal = 'Thermal'
|
||||
|
|
|
@ -4,7 +4,7 @@ from enum import Enum
|
|||
from typing import List, Set
|
||||
|
||||
import marshmallow as ma
|
||||
from flask import jsonify, request
|
||||
from flask import Response, jsonify, request
|
||||
from marshmallow import Schema as MarshmallowSchema, fields as f
|
||||
from teal.marshmallow import EnumField
|
||||
from teal.resource import View
|
||||
|
@ -36,6 +36,14 @@ class LotView(View):
|
|||
ret.status_code = 201
|
||||
return ret
|
||||
|
||||
def patch(self, id):
|
||||
l = request.get_json()
|
||||
lot = Lot.query.filter_by(id=id).one()
|
||||
for key, value in l.items():
|
||||
setattr(lot, key, value)
|
||||
db.session.commit()
|
||||
return Response(status=204)
|
||||
|
||||
def one(self, id: uuid.UUID):
|
||||
"""Gets one event."""
|
||||
lot = Lot.query.filter_by(id=id).one() # type: Lot
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from sqlalchemy import Column
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column
|
||||
from teal.db import Model
|
||||
|
||||
STR_SIZE = 64
|
||||
|
@ -13,3 +14,8 @@ class Thing(Model):
|
|||
type = ... # type: str
|
||||
updated = ... # type: Column
|
||||
created = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
self.updated = ... # type: datetime
|
||||
self.created = ... # type: datetime
|
||||
|
|
|
@ -22,8 +22,8 @@ class UnitCodes(Enum):
|
|||
class Thing(Schema):
|
||||
type = String(description='Only required when it is nested.')
|
||||
same_as = List(URL(dump_only=True), dump_only=True, data_key='sameAs')
|
||||
updated = DateTime('iso', dump_only=True, description=m.Thing.updated.comment.strip())
|
||||
created = DateTime('iso', dump_only=True, description=m.Thing.created.comment.strip())
|
||||
updated = DateTime('iso', dump_only=True, description=m.Thing.updated.comment)
|
||||
created = DateTime('iso', dump_only=True, description=m.Thing.created.comment)
|
||||
|
||||
@post_load
|
||||
def remove_type(self, data: dict):
|
||||
|
|
|
@ -25,7 +25,7 @@ requests==2.19.1
|
|||
requests-mock==1.5.2
|
||||
SQLAlchemy==1.2.11
|
||||
SQLAlchemy-Utils==0.33.3
|
||||
teal==0.2.0a25
|
||||
teal==0.2.0a26
|
||||
webargs==4.0.0
|
||||
Werkzeug==0.14.1
|
||||
sqlalchemy-citext==1.3.post0
|
||||
|
|
2
setup.py
2
setup.py
|
@ -34,7 +34,7 @@ setup(
|
|||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
install_requires=[
|
||||
'teal>=0.2.0a25', # teal always first
|
||||
'teal>=0.2.0a26', # teal always first
|
||||
'click',
|
||||
'click-spinner',
|
||||
'ereuse-utils[Naming]>=0.4b9',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../../ereuse_devicehub/dummy/files/keyboard.snapshot.yaml
|
|
@ -40,4 +40,4 @@ def test_api_docs(client: Client):
|
|||
'scheme': 'basic',
|
||||
'name': 'Authorization'
|
||||
}
|
||||
assert 75 == len(docs['definitions'])
|
||||
assert 92 == len(docs['definitions'])
|
||||
|
|
|
@ -9,16 +9,15 @@ from ereuse_utils.test import ANY
|
|||
from pytest import raises
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from teal.db import ResourceNotFound
|
||||
from teal.enums import Layouts
|
||||
|
||||
from ereuse_devicehub.client import Client, UserClient
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.devicehub import Devicehub
|
||||
from ereuse_devicehub.resources.agent.models import Person
|
||||
from ereuse_devicehub.resources.device import models as d
|
||||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||
from ereuse_devicehub.resources.device.models import Component, ComputerMonitor, DataStorage, \
|
||||
Desktop, Device, GraphicCard, Laptop, Motherboard, NetworkAdapter
|
||||
from ereuse_devicehub.resources.device.schemas import Device as DeviceS
|
||||
from ereuse_devicehub.resources.device.search import DeviceSearch
|
||||
from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \
|
||||
Sync
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech
|
||||
|
@ -35,43 +34,43 @@ def test_device_model():
|
|||
"""
|
||||
Tests that the correctness of the device model and its relationships.
|
||||
"""
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
net = NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
||||
graphic = GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
net = d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
||||
graphic = d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
pc.components.add(net)
|
||||
pc.components.add(graphic)
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
pc = Desktop.query.one()
|
||||
pc = d.Desktop.query.one()
|
||||
assert pc.serial_number == 'p1s'
|
||||
assert pc.components == OrderedSet([net, graphic])
|
||||
network_adapter = NetworkAdapter.query.one()
|
||||
network_adapter = d.NetworkAdapter.query.one()
|
||||
assert network_adapter.parent == pc
|
||||
|
||||
# Removing a component from pc doesn't delete the component
|
||||
pc.components.remove(net)
|
||||
db.session.commit()
|
||||
pc = Device.query.first() # this is the same as querying for Desktop directly
|
||||
pc = d.Device.query.first() # this is the same as querying for d.Desktop directly
|
||||
assert pc.components == {graphic}
|
||||
network_adapter = NetworkAdapter.query.one()
|
||||
network_adapter = d.NetworkAdapter.query.one()
|
||||
assert network_adapter not in pc.components
|
||||
assert network_adapter.parent is None
|
||||
|
||||
# Deleting the pc deletes everything
|
||||
gcard = GraphicCard.query.one()
|
||||
gcard = d.GraphicCard.query.one()
|
||||
db.session.delete(pc)
|
||||
db.session.flush()
|
||||
assert pc.id == 1
|
||||
assert Desktop.query.first() is None
|
||||
assert d.Desktop.query.first() is None
|
||||
db.session.commit()
|
||||
assert Desktop.query.first() is None
|
||||
assert d.Desktop.query.first() is None
|
||||
assert network_adapter.id == 2
|
||||
assert NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
||||
assert d.NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
||||
assert gcard.id == 3, 'We should still hold a reference to a zombie graphic card'
|
||||
assert GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'
|
||||
assert d.GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
|
@ -79,26 +78,26 @@ def test_device_schema():
|
|||
"""Ensures the user does not upload non-writable or extra fields."""
|
||||
device_s = DeviceS()
|
||||
device_s.load({'serialNumber': 'foo1', 'model': 'foo', 'manufacturer': 'bar2'})
|
||||
device_s.dump(Device(id=1))
|
||||
device_s.dump(d.Device(id=1))
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_physical_properties():
|
||||
c = Motherboard(slots=2,
|
||||
usb=3,
|
||||
serial_number='sn',
|
||||
model='ml',
|
||||
manufacturer='mr',
|
||||
width=2.0,
|
||||
color=Color())
|
||||
pc = Desktop(chassis=ComputerChassis.Tower,
|
||||
model='foo',
|
||||
manufacturer='bar',
|
||||
serial_number='foo-bar',
|
||||
weight=2.8,
|
||||
width=1.4,
|
||||
height=2.1,
|
||||
color=Color('LightSeaGreen'))
|
||||
c = d.Motherboard(slots=2,
|
||||
usb=3,
|
||||
serial_number='sn',
|
||||
model='ml',
|
||||
manufacturer='mr',
|
||||
width=2.0,
|
||||
color=Color())
|
||||
pc = d.Desktop(chassis=ComputerChassis.Tower,
|
||||
model='foo',
|
||||
manufacturer='bar',
|
||||
serial_number='foo-bar',
|
||||
weight=2.8,
|
||||
width=1.4,
|
||||
height=2.1,
|
||||
color=Color('LightSeaGreen'))
|
||||
pc.components.add(c)
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
@ -114,7 +113,6 @@ def test_physical_properties():
|
|||
'weight': None,
|
||||
'height': None,
|
||||
'width': 2.0,
|
||||
'color': Color(),
|
||||
'depth': None
|
||||
}
|
||||
assert pc.physical_properties == {
|
||||
|
@ -125,7 +123,6 @@ def test_physical_properties():
|
|||
'width': 1.4,
|
||||
'height': 2.1,
|
||||
'depth': None,
|
||||
'color': Color('LightSeaGreen'),
|
||||
'chassis': ComputerChassis.Tower
|
||||
}
|
||||
|
||||
|
@ -133,18 +130,18 @@ def test_physical_properties():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_component_similar_one():
|
||||
snapshot = conftest.file('pc-components.db')
|
||||
d = snapshot['device']
|
||||
pc = snapshot['device']
|
||||
snapshot['components'][0]['serial_number'] = snapshot['components'][1]['serial_number'] = None
|
||||
pc = Desktop(**d, components=OrderedSet(Component(**c) for c in snapshot['components']))
|
||||
component1, component2 = pc.components # type: Component
|
||||
pc = d.Desktop(**pc, components=OrderedSet(d.Component(**c) for c in snapshot['components']))
|
||||
component1, component2 = pc.components # type: d.Component
|
||||
db.session.add(pc)
|
||||
db.session.flush()
|
||||
# Let's create a new component named 'A' similar to 1
|
||||
componentA = Component(model=component1.model, manufacturer=component1.manufacturer)
|
||||
componentA = d.Component(model=component1.model, manufacturer=component1.manufacturer)
|
||||
similar_to_a = componentA.similar_one(pc, set())
|
||||
assert similar_to_a == component1
|
||||
# Component B does not have the same model
|
||||
componentB = Component(model='nope', manufacturer=component1.manufacturer)
|
||||
# d.Component B does not have the same model
|
||||
componentB = d.Component(model='nope', manufacturer=component1.manufacturer)
|
||||
with pytest.raises(ResourceNotFound):
|
||||
assert componentB.similar_one(pc, set())
|
||||
# If we blacklist component A we won't get anything
|
||||
|
@ -160,14 +157,14 @@ def test_add_remove():
|
|||
# c4 is not with any pc
|
||||
values = conftest.file('pc-components.db')
|
||||
pc = values['device']
|
||||
c1, c2 = (Component(**c) for c in values['components'])
|
||||
pc = Desktop(**pc, components=OrderedSet([c1, c2]))
|
||||
c1, c2 = (d.Component(**c) for c in values['components'])
|
||||
pc = d.Desktop(**pc, components=OrderedSet([c1, c2]))
|
||||
db.session.add(pc)
|
||||
c3 = Component(serial_number='nc1')
|
||||
pc2 = Desktop(serial_number='s2',
|
||||
components=OrderedSet([c3]),
|
||||
chassis=ComputerChassis.Microtower)
|
||||
c4 = Component(serial_number='c4s')
|
||||
c3 = d.Component(serial_number='nc1')
|
||||
pc2 = d.Desktop(serial_number='s2',
|
||||
components=OrderedSet([c3]),
|
||||
chassis=ComputerChassis.Microtower)
|
||||
c4 = d.Component(serial_number='c4s')
|
||||
db.session.add(pc2)
|
||||
db.session.add(c4)
|
||||
db.session.commit()
|
||||
|
@ -190,12 +187,12 @@ def test_sync_run_components_empty():
|
|||
remove all the components from the device.
|
||||
"""
|
||||
s = conftest.file('pc-components.db')
|
||||
pc = Desktop(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
|
||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db synced object
|
||||
pc = Desktop(**s['device'])
|
||||
pc = d.Desktop(**s['device'])
|
||||
db_pc, _ = Sync().run(pc, components=OrderedSet())
|
||||
assert not db_pc.components
|
||||
assert not pc.components
|
||||
|
@ -208,25 +205,25 @@ def test_sync_run_components_none():
|
|||
keep all the components from the device.
|
||||
"""
|
||||
s = conftest.file('pc-components.db')
|
||||
pc = Desktop(**s['device'], components=OrderedSet(Component(**c) for c in s['components']))
|
||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db synced object
|
||||
transient_pc = Desktop(**s['device'])
|
||||
transient_pc = d.Desktop(**s['device'])
|
||||
db_pc, _ = Sync().run(transient_pc, components=None)
|
||||
assert db_pc.components
|
||||
assert db_pc.components == pc.components
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_new_Desktop_no_tag():
|
||||
def test_sync_execute_register_desktop_new_desktop_no_tag():
|
||||
"""
|
||||
Syncs a new Desktop with HID and without a tag, creating it.
|
||||
Syncs a new d.Desktop with HID and without a tag, creating it.
|
||||
:return:
|
||||
"""
|
||||
# Case 1: device does not exist on DB
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db_pc = Sync().execute_register(pc)
|
||||
assert pc.physical_properties == db_pc.physical_properties
|
||||
|
||||
|
@ -234,13 +231,13 @@ def test_sync_execute_register_desktop_new_Desktop_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_existing_no_tag():
|
||||
"""
|
||||
Syncs an existing Desktop with HID and without a tag.
|
||||
Syncs an existing d.Desktop with HID and without a tag.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(pc)
|
||||
db.session.commit()
|
||||
|
||||
pc = Desktop(
|
||||
pc = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
# 1: device exists on DB
|
||||
db_pc = Sync().execute_register(pc)
|
||||
|
@ -250,11 +247,11 @@ def test_sync_execute_register_desktop_existing_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_no_hid_no_tag():
|
||||
"""
|
||||
Syncs a Desktop without HID and no tag.
|
||||
Syncs a d.Desktop without HID and no tag.
|
||||
|
||||
This should fail as we don't have a way to identify it.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
# 1: device has no HID
|
||||
pc.hid = pc.model = None
|
||||
with pytest.raises(NeedsId):
|
||||
|
@ -264,7 +261,7 @@ def test_sync_execute_register_desktop_no_hid_no_tag():
|
|||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_desktop_tag_not_linked():
|
||||
"""
|
||||
Syncs a new Desktop with HID and a non-linked tag.
|
||||
Syncs a new d.Desktop with HID and a non-linked tag.
|
||||
|
||||
It is OK if the tag was not linked, it will be linked in this process.
|
||||
"""
|
||||
|
@ -273,24 +270,24 @@ def test_sync_execute_register_desktop_tag_not_linked():
|
|||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db object
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')]))
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
assert returned_pc == pc
|
||||
assert tag.device == pc, 'Tag has to be linked'
|
||||
assert Desktop.query.one() == pc, 'Desktop had to be set to db'
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
|
||||
"""
|
||||
Validates registering a Desktop without HID and a non-linked tag.
|
||||
Validates registering a d.Desktop without HID and a non-linked tag.
|
||||
|
||||
In this case it is ok still, as the non-linked tag proves that
|
||||
the Desktop was not existing before (otherwise the tag would
|
||||
be linked), and thus it creates a new Desktop.
|
||||
the d.Desktop was not existing before (otherwise the tag would
|
||||
be linked), and thus it creates a new d.Desktop.
|
||||
"""
|
||||
tag = Tag(id=tag_id)
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([tag]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([tag]))
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
db.session.commit()
|
||||
assert returned_pc == pc
|
||||
|
@ -300,7 +297,7 @@ def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
|
|||
# they have the same pk though
|
||||
assert tag != db_tag, 'They are not the same tags though'
|
||||
assert db_tag.id == tag.id
|
||||
assert Desktop.query.one() == pc, 'Desktop had to be set to db'
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
|
@ -311,7 +308,7 @@ def test_sync_execute_register_tag_does_not_exist():
|
|||
|
||||
Tags have to be created before trying to link them through a Snapshot.
|
||||
"""
|
||||
pc = Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag('foo')]))
|
||||
pc = d.Desktop(**conftest.file('pc-components.db')['device'], tags=OrderedSet([Tag('foo')]))
|
||||
with raises(ResourceNotFound):
|
||||
Sync().execute_register(pc)
|
||||
|
||||
|
@ -324,11 +321,11 @@ def test_sync_execute_register_tag_linked_same_device():
|
|||
(If it has HID it validates both HID and tag point at the same
|
||||
device, this his checked in ).
|
||||
"""
|
||||
orig_pc = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
orig_pc = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo', device=orig_pc))
|
||||
db.session.commit()
|
||||
|
||||
pc = Desktop(
|
||||
pc = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc.tags.add(Tag(id='foo'))
|
||||
db_pc = Sync().execute_register(pc)
|
||||
|
@ -343,15 +340,15 @@ def test_sync_execute_register_tag_linked_other_device_mismatch_between_tags():
|
|||
Checks that sync raises an error if finds that at least two passed-in
|
||||
tags are not linked to the same device.
|
||||
"""
|
||||
pc1 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc1 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = Desktop(
|
||||
pc1 = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-1'))
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
|
@ -367,15 +364,15 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
|||
|
||||
In this case we set HID -> pc1 but tag -> pc2
|
||||
"""
|
||||
pc1 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc1 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2 = d.Desktop(**conftest.file('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.manufacturer, pc2.serial_number, pc2.model)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = Desktop(
|
||||
pc1 = d.Desktop(
|
||||
**conftest.file('pc-components.db')['device']) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
with raises(MismatchBetweenTagsAndHid):
|
||||
|
@ -383,15 +380,15 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
|||
|
||||
|
||||
def test_get_device(app: Devicehub, user: UserClient):
|
||||
"""Checks GETting a Desktop with its components."""
|
||||
"""Checks GETting a d.Desktop with its components."""
|
||||
with app.app_context():
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc.components = OrderedSet([
|
||||
NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
])
|
||||
db.session.add(pc)
|
||||
db.session.add(Test(device=pc,
|
||||
|
@ -400,7 +397,7 @@ def test_get_device(app: Devicehub, user: UserClient):
|
|||
agent=Person(name='Timmy'),
|
||||
author=User(email='bar@bar.com')))
|
||||
db.session.commit()
|
||||
pc, _ = user.get(res=Device, item=1)
|
||||
pc, _ = user.get(res=d.Device, item=1)
|
||||
assert len(pc['events']) == 1
|
||||
assert pc['events'][0]['type'] == 'Test'
|
||||
assert pc['events'][0]['device'] == 1
|
||||
|
@ -415,46 +412,46 @@ def test_get_device(app: Devicehub, user: UserClient):
|
|||
assert pc['model'] == 'p1mo'
|
||||
assert pc['manufacturer'] == 'p1ma'
|
||||
assert pc['serialNumber'] == 'p1s'
|
||||
assert pc['type'] == 'Desktop'
|
||||
assert pc['type'] == d.Desktop.t
|
||||
|
||||
|
||||
def test_get_devices(app: Devicehub, user: UserClient):
|
||||
"""Checks GETting multiple devices."""
|
||||
with app.app_context():
|
||||
pc = Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc = d.Desktop(model='p1mo',
|
||||
manufacturer='p1ma',
|
||||
serial_number='p1s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc.components = OrderedSet([
|
||||
NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s'),
|
||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||
])
|
||||
pc1 = Desktop(model='p2mo',
|
||||
manufacturer='p2ma',
|
||||
serial_number='p2s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc2 = Laptop(model='p3mo',
|
||||
manufacturer='p3ma',
|
||||
serial_number='p3s',
|
||||
chassis=ComputerChassis.Netbook)
|
||||
pc1 = d.Desktop(model='p2mo',
|
||||
manufacturer='p2ma',
|
||||
serial_number='p2s',
|
||||
chassis=ComputerChassis.Tower)
|
||||
pc2 = d.Laptop(model='p3mo',
|
||||
manufacturer='p3ma',
|
||||
serial_number='p3s',
|
||||
chassis=ComputerChassis.Netbook)
|
||||
db.session.add_all((pc, pc1, pc2))
|
||||
db.session.commit()
|
||||
devices, _ = user.get(res=Device)
|
||||
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'
|
||||
devices, _ = user.get(res=d.Device)
|
||||
assert tuple(dev['id'] for dev in devices['items']) == (1, 2, 3, 4, 5)
|
||||
assert tuple(dev['type'] for dev in devices['items']) == (
|
||||
d.Desktop.t, d.Desktop.t, d.Laptop.t, d.NetworkAdapter.t, d.GraphicCard.t
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_computer_monitor():
|
||||
m = ComputerMonitor(technology=DisplayTech.LCD,
|
||||
manufacturer='foo',
|
||||
model='bar',
|
||||
serial_number='foo-bar',
|
||||
resolution_width=1920,
|
||||
resolution_height=1080,
|
||||
size=14.5)
|
||||
m = d.ComputerMonitor(technology=DisplayTech.LCD,
|
||||
manufacturer='foo',
|
||||
model='bar',
|
||||
serial_number='foo-bar',
|
||||
resolution_width=1920,
|
||||
resolution_height=1080,
|
||||
size=14.5)
|
||||
db.session.add(m)
|
||||
db.session.commit()
|
||||
|
||||
|
@ -474,22 +471,8 @@ def test_computer_with_display():
|
|||
pass
|
||||
|
||||
|
||||
def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClient):
|
||||
"""Ensures DeviceSearch can regenerate itself when the table is empty."""
|
||||
user.post(file('basic.snapshot'), res=m.Snapshot)
|
||||
with app.app_context():
|
||||
app.db.session.execute('TRUNCATE TABLE {}'.format(DeviceSearch.__table__.name))
|
||||
app.db.session.commit()
|
||||
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=Device, query=[('search', 'Desktop')])
|
||||
assert not len(i['items'])
|
||||
|
||||
|
||||
def test_manufacturer(user: UserClient):
|
||||
m, r = user.get(res='Manufacturer', query=[('name', 'asus')])
|
||||
m, r = user.get(res='Manufacturer', query=[('search', 'asus')])
|
||||
assert m == {'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]}
|
||||
assert r.cache_control.public
|
||||
assert r.expires > datetime.datetime.now()
|
||||
|
@ -504,7 +487,7 @@ def test_manufacturer_enforced():
|
|||
def test_device_properties_format(app: Devicehub, user: UserClient):
|
||||
user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||
with app.app_context():
|
||||
pc = Laptop.query.one() # type: Laptop
|
||||
pc = d.Laptop.query.one() # type: d.Laptop
|
||||
assert format(pc) == 'Laptop 1: model 1000h, S/N 94oaaq021116'
|
||||
assert format(pc, 't') == 'Netbook 1000h'
|
||||
assert format(pc, 's') == '(asustek computer inc.) S/N 94OAAQ021116'
|
||||
|
@ -512,12 +495,12 @@ def test_device_properties_format(app: Devicehub, user: UserClient):
|
|||
assert pc.data_storage_size == 152627
|
||||
assert pc.graphic_card_model == 'mobile 945gse express integrated graphics controller'
|
||||
assert pc.processor_model == 'intel atom cpu n270 @ 1.60ghz'
|
||||
net = next(c for c in pc.components if isinstance(c, NetworkAdapter))
|
||||
net = next(c for c in pc.components if isinstance(c, d.NetworkAdapter))
|
||||
assert format(net) == 'NetworkAdapter 2: model ar8121/ar8113/ar8114 ' \
|
||||
'gigabit or fast ethernet, S/N 00:24:8c:7f:cf:2d'
|
||||
assert format(net, 't') == 'NetworkAdapter ar8121/ar8113/ar8114 gigabit or fast ethernet'
|
||||
assert format(net, 's') == '(qualcomm atheros) S/N 00:24:8C:7F:CF:2D – 100 Mbps'
|
||||
hdd = next(c for c in pc.components if isinstance(c, DataStorage))
|
||||
hdd = next(c for c in pc.components if isinstance(c, d.DataStorage))
|
||||
assert format(hdd) == 'HardDrive 7: model st9160310as, S/N 5sv4tqa6'
|
||||
assert format(hdd, 't') == 'HardDrive st9160310as'
|
||||
assert format(hdd, 's') == '(seagate) S/N 5SV4TQA6 – 152 GB'
|
||||
|
@ -525,13 +508,26 @@ def test_device_properties_format(app: Devicehub, user: UserClient):
|
|||
|
||||
def test_device_public(user: UserClient, client: Client):
|
||||
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||
html, _ = client.get(res=Device, item=s['device']['id'], accept=ANY)
|
||||
html, _ = client.get(res=d.Device, item=s['device']['id'], accept=ANY)
|
||||
assert 'intel atom cpu n270 @ 1.60ghz' in html
|
||||
assert 'S/N 00:24:8C:7F:CF:2D – 100 Mbps' in html
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='Functionality not yet developed.')
|
||||
def test_device_search_multiple_tags(user: UserClient):
|
||||
"""Ensures that users can search multiple tags at once
|
||||
and get their multiple devices."""
|
||||
pass
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_computer_accessory_model():
|
||||
sai = d.SAI()
|
||||
db.session.add(sai)
|
||||
keyboard = d.Keyboard(layout=Layouts.ES)
|
||||
db.session.add(keyboard)
|
||||
mouse = d.Mouse()
|
||||
db.session.add(mouse)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_networking_model():
|
||||
router = d.Router(speed=1000, wireless=True)
|
||||
db.session.add(router)
|
||||
switch = d.Switch(speed=1000, wireless=False)
|
||||
db.session.add(switch)
|
||||
db.session.commit()
|
||||
|
|
|
@ -6,6 +6,7 @@ from ereuse_devicehub.db import db
|
|||
from ereuse_devicehub.devicehub import Devicehub
|
||||
from ereuse_devicehub.resources.device.models import Desktop, Device, Laptop, Processor, \
|
||||
SolidStateDrive
|
||||
from ereuse_devicehub.resources.device.search import DeviceSearch
|
||||
from ereuse_devicehub.resources.device.views import Filters, Sorting
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis
|
||||
from ereuse_devicehub.resources.event.models import Snapshot
|
||||
|
@ -174,6 +175,21 @@ def test_device_lots_query(user: UserClient):
|
|||
pass
|
||||
|
||||
|
||||
def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClient):
|
||||
"""Ensures DeviceSearch can regenerate itself when the table is empty."""
|
||||
user.post(file('basic.snapshot'), res=Snapshot)
|
||||
with app.app_context():
|
||||
app.db.session.execute('TRUNCATE TABLE {}'.format(DeviceSearch.__table__.name))
|
||||
app.db.session.commit()
|
||||
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)
|
||||
app.db.session.commit()
|
||||
i, _ = user.get(res=Device, query=[('search', 'Desktop')])
|
||||
assert i['items']
|
||||
|
||||
|
||||
def test_device_query_search(user: UserClient):
|
||||
# todo improve
|
||||
user.post(file('basic.snapshot'), res=Snapshot)
|
||||
|
|
|
@ -112,7 +112,10 @@ def test_install():
|
|||
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_update_components_event_one():
|
||||
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1')
|
||||
computer = Desktop(serial_number='sn1',
|
||||
model='ml1',
|
||||
manufacturer='mr1',
|
||||
chassis=ComputerChassis.Tower)
|
||||
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
|
||||
computer.components.add(hdd)
|
||||
|
||||
|
@ -137,7 +140,10 @@ def test_update_components_event_one():
|
|||
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_update_components_event_multiple():
|
||||
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1')
|
||||
computer = Desktop(serial_number='sn1',
|
||||
model='ml1',
|
||||
manufacturer='mr1',
|
||||
chassis=ComputerChassis.Tower)
|
||||
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
|
||||
computer.components.add(hdd)
|
||||
|
||||
|
@ -163,7 +169,10 @@ def test_update_components_event_multiple():
|
|||
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_update_parent():
|
||||
computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1')
|
||||
computer = Desktop(serial_number='sn1',
|
||||
model='ml1',
|
||||
manufacturer='mr1',
|
||||
chassis=ComputerChassis.Tower)
|
||||
hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar')
|
||||
computer.components.add(hdd)
|
||||
|
||||
|
|
|
@ -23,6 +23,15 @@ In case of error, debug with:
|
|||
"""
|
||||
|
||||
|
||||
def test_lot_modify_patch_endpoint(user: UserClient):
|
||||
"""Creates and modifies lot properties through the endpoint"""
|
||||
l, _ = user.post({'name': 'foo'}, res=Lot)
|
||||
assert l['name'] == 'foo'
|
||||
user.patch({'name': 'bar'}, res=Lot, item=l['id'], status=204)
|
||||
l_after, _ = user.get(res=Lot, item=l['id'])
|
||||
assert l_after['name'] == 'bar'
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='Components are not added to lots!')
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_lot_device_relationship():
|
||||
|
|
|
@ -51,7 +51,7 @@ def test_rate():
|
|||
appearance_range=AppearanceRange.A,
|
||||
functionality_range=FunctionalityRange.A
|
||||
)
|
||||
pc = Desktop()
|
||||
pc = Desktop(chassis=ComputerChassis.Tower)
|
||||
hdd = HardDrive(size=476940)
|
||||
hdd.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8))
|
||||
cpu = Processor(cores=2, speed=3.4)
|
||||
|
|
|
@ -15,7 +15,7 @@ Excluded cases in tests
|
|||
import pytest
|
||||
|
||||
from ereuse_devicehub.resources.device.models import Desktop, HardDrive, Processor, RamModule
|
||||
from ereuse_devicehub.resources.enums import AppearanceRange, FunctionalityRange
|
||||
from ereuse_devicehub.resources.enums import AppearanceRange, ComputerChassis, FunctionalityRange
|
||||
from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, BenchmarkProcessor, \
|
||||
WorkbenchRate
|
||||
from ereuse_devicehub.resources.event.rate.workbench.v1_0 import DataStorageRate, ProcessorRate, \
|
||||
|
@ -307,7 +307,7 @@ def test_rate_computer_rate():
|
|||
"""
|
||||
|
||||
# Create a new Computer with components characteristics of pc with id = 1193
|
||||
pc_test = Desktop()
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=476940)
|
||||
data_storage.events_one.add(BenchmarkDataStorage(read_speed=126, write_speed=29.8))
|
||||
cpu = Processor(cores=2, speed=3.4)
|
||||
|
@ -333,7 +333,7 @@ def test_rate_computer_rate():
|
|||
assert round(rate_pc.rating, 2) == 4.61
|
||||
|
||||
# Create a new Computer with components characteristics of pc with id = 1201
|
||||
pc_test = Desktop()
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=476940)
|
||||
data_storage.events_one.add(BenchmarkDataStorage(read_speed=158, write_speed=34.7))
|
||||
cpu = Processor(cores=2, speed=3.3)
|
||||
|
@ -358,7 +358,7 @@ def test_rate_computer_rate():
|
|||
assert round(rate_pc.rating, 2) == 3.48
|
||||
|
||||
# Create a new Computer with components characteristics of pc with id = 79
|
||||
pc_test = Desktop()
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=76319)
|
||||
data_storage.events_one.add(BenchmarkDataStorage(read_speed=72.2, write_speed=24.3))
|
||||
cpu = Processor(cores=1, speed=1.6)
|
||||
|
@ -386,7 +386,7 @@ def test_rate_computer_rate():
|
|||
assert round(rate_pc.rating, 2) == 1.58
|
||||
|
||||
# Create a new Computer with components characteristics of pc with id = 798
|
||||
pc_test = Desktop()
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=152587)
|
||||
data_storage.events_one.add(BenchmarkDataStorage(read_speed=78.1, write_speed=24.4))
|
||||
cpu = Processor(cores=2, speed=2.5)
|
||||
|
|
|
@ -411,3 +411,10 @@ def snapshot_and_check(user: UserClient,
|
|||
return snapshot_and_check(user, input_snapshot, event_types, perform_second_snapshot=False)
|
||||
else:
|
||||
return snapshot
|
||||
|
||||
|
||||
def test_snapshot_keyboard(user: UserClient):
|
||||
s = file('keyboard.snapshot')
|
||||
snapshot = snapshot_and_check(user, s, event_types=('ManualRate',))
|
||||
keyboard = snapshot['device']
|
||||
assert keyboard['layout'] == 'ES'
|
||||
|
|
|
@ -155,8 +155,11 @@ def test_tag_create_etags_cli(app: Devicehub, user: UserClient):
|
|||
assert tag.provider == URL('https://t.ereuse.org')
|
||||
|
||||
|
||||
def test_tag_manual_link(app: Devicehub, user: UserClient):
|
||||
"""Tests linking manually a tag through PUT /tags/<id>/device/<id>"""
|
||||
def test_tag_manual_link_search(app: Devicehub, user: UserClient):
|
||||
"""Tests linking manually a tag through PUT /tags/<id>/device/<id>
|
||||
|
||||
Checks search has the term.
|
||||
"""
|
||||
with app.app_context():
|
||||
db.session.add(Tag('foo-bar', secondary='foo-sec'))
|
||||
desktop = Desktop(serial_number='foo', chassis=ComputerChassis.AllInOne)
|
||||
|
@ -179,6 +182,13 @@ def test_tag_manual_link(app: Devicehub, user: UserClient):
|
|||
# cannot link to another device when already linked
|
||||
user.put({}, res=Tag, item='foo-bar/device/99', status=LinkedToAnotherDevice)
|
||||
|
||||
i, _ = user.get(res=Device, query=[('search', 'foo-bar')])
|
||||
assert i['items']
|
||||
i, _ = user.get(res=Device, query=[('search', 'foo-sec')])
|
||||
assert i['items']
|
||||
i, _ = user.get(res=Device, query=[('search', 'foo')])
|
||||
assert i['items']
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_tag_secondary_workbench_link_find(user: UserClient):
|
||||
|
|
|
@ -142,6 +142,9 @@ def test_real_hp_11(user: UserClient):
|
|||
assert pc['hid'] == 'hewlett-packard-czc0408yjg-hp_compaq_8100_elite_sff'
|
||||
assert pc['chassis'] == 'Tower'
|
||||
assert set(e['type'] for e in snapshot['events']) == {
|
||||
'EreusePrice',
|
||||
'AggregateRate',
|
||||
'WorkbenchRate',
|
||||
'BenchmarkDataStorage',
|
||||
'BenchmarkProcessor',
|
||||
'BenchmarkProcessorSysbench',
|
||||
|
@ -149,11 +152,12 @@ def test_real_hp_11(user: UserClient):
|
|||
'BenchmarkRamSysbench',
|
||||
'StressTest'
|
||||
}
|
||||
assert len(list(e['type'] for e in snapshot['events'])) == 6
|
||||
assert len(list(e['type'] for e in snapshot['events'])) == 9
|
||||
assert pc['networkSpeeds'] == [1000, None], 'Device has no WiFi'
|
||||
assert pc['processorModel'] == 'intel core i3 cpu 530 @ 2.93ghz'
|
||||
assert pc['ramSize'] == 8192
|
||||
assert pc['dataStorageSize'] == 305245
|
||||
# todo check rating
|
||||
|
||||
|
||||
def test_real_toshiba_11(user: UserClient):
|
||||
|
@ -177,6 +181,20 @@ def test_snapshot_real_eee_1001pxd(user: UserClient):
|
|||
assert pc['hid'] == 'asustek_computer_inc-b8oaas048286-1001pxd'
|
||||
assert pc['tags'] == []
|
||||
assert pc['networkSpeeds'] == [100, 0], 'Although it has WiFi we do not know the speed'
|
||||
assert pc['rate']
|
||||
rate = pc['rate']
|
||||
assert rate['appearanceRange'] == 'B'
|
||||
assert rate['functionalityRange'] == 'A'
|
||||
assert rate['processorRange'] == 'VERY_LOW'
|
||||
assert rate['ramRange'] == 'VERY_LOW'
|
||||
assert rate['ratingRange'] == 'VERY_LOW'
|
||||
assert rate['ram'] == 1.53
|
||||
assert rate['data_storage'] == 3.76
|
||||
assert rate['type'] == 'AggregateRate'
|
||||
assert rate['biosRange'] == 'C'
|
||||
assert rate['appearance'] > 0
|
||||
assert rate['functionality'] > 0
|
||||
assert rate['rating'] > 0 and rate['rating'] != 1
|
||||
components = snapshot['components']
|
||||
wifi = components[0]
|
||||
assert wifi['hid'] == 'qualcomm_atheros-74_2f_68_8b_fd_c8-ar9285_wireless_network_adapter'
|
||||
|
@ -208,7 +226,7 @@ def test_snapshot_real_eee_1001pxd(user: UserClient):
|
|||
assert em.BenchmarkRamSysbench.t in event_types
|
||||
assert em.StressTest.t in event_types
|
||||
assert em.Snapshot.t in event_types
|
||||
assert len(events) == 5
|
||||
assert len(events) == 7
|
||||
gpu = components[3]
|
||||
assert gpu['model'] == 'atom processor d4xx/d5xx/n4xx/n5xx integrated graphics controller'
|
||||
assert gpu['manufacturer'] == 'intel corporation'
|
||||
|
|
Reference in New Issue