Move export to Documents
This commit is contained in:
parent
208814ecf2
commit
13ffab7022
|
@ -1,14 +1,10 @@
|
||||||
import csv
|
|
||||||
import datetime
|
import datetime
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
import marshmallow
|
import marshmallow
|
||||||
from flask import current_app as app, render_template, request, make_response
|
from flask import current_app as app, render_template, request
|
||||||
from flask.json import jsonify
|
from flask.json import jsonify
|
||||||
from flask_sqlalchemy import Pagination
|
from flask_sqlalchemy import Pagination
|
||||||
from marshmallow import fields, fields as f, validate as v
|
from marshmallow import fields, fields as f, validate as v
|
||||||
from sqlalchemy.orm import aliased
|
|
||||||
from sqlalchemy.util import OrderedDict
|
|
||||||
from teal import query
|
from teal import query
|
||||||
from teal.cache import cache
|
from teal.cache import cache
|
||||||
from teal.resource import View
|
from teal.resource import View
|
||||||
|
@ -17,9 +13,7 @@ from ereuse_devicehub import auth
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.query import SearchQueryParser, things_response
|
from ereuse_devicehub.query import SearchQueryParser, things_response
|
||||||
from ereuse_devicehub.resources import search
|
from ereuse_devicehub.resources import search
|
||||||
from ereuse_devicehub.resources.device.models import Component, Computer, Device, Manufacturer, \
|
from ereuse_devicehub.resources.device.models import Device, Manufacturer
|
||||||
Display, Processor, GraphicCard, Motherboard, NetworkAdapter, DataStorage, RamModule, \
|
|
||||||
SoundCard
|
|
||||||
from ereuse_devicehub.resources.device.search import DeviceSearch
|
from ereuse_devicehub.resources.device.search import DeviceSearch
|
||||||
from ereuse_devicehub.resources.event import models as events
|
from ereuse_devicehub.resources.event import models as events
|
||||||
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
|
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
|
||||||
|
@ -138,150 +132,7 @@ class DeviceView(View):
|
||||||
).order_by(
|
).order_by(
|
||||||
search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p)
|
search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p)
|
||||||
)
|
)
|
||||||
query = query.filter(*args['filter']).order_by(*args['sort'])
|
return query.filter(*args['filter']).order_by(*args['sort'])
|
||||||
if 'text/csv' in request.accept_mimetypes:
|
|
||||||
return self.generate_post_csv(query)
|
|
||||||
else:
|
|
||||||
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,
|
|
||||||
'previous': devices.prev_num,
|
|
||||||
'next': devices.next_num
|
|
||||||
},
|
|
||||||
'url': request.path
|
|
||||||
}
|
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
def generate_post_csv(self, query):
|
|
||||||
"""
|
|
||||||
Get device query and put information in csv format
|
|
||||||
:param query:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
data = StringIO()
|
|
||||||
cw = csv.writer(data)
|
|
||||||
first = True
|
|
||||||
for device in query:
|
|
||||||
d = DeviceRow(device)
|
|
||||||
if first:
|
|
||||||
cw.writerow(name for name in d.keys())
|
|
||||||
first = False
|
|
||||||
cw.writerow(v for v in d.values())
|
|
||||||
output = make_response(data.getvalue())
|
|
||||||
output.headers['Content-Disposition'] = 'attachment; filename=export.csv'
|
|
||||||
output.headers['Content-type'] = 'text/csv'
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceRow(OrderedDict):
|
|
||||||
NUMS = {
|
|
||||||
Display.t: 1,
|
|
||||||
Processor.t: 2,
|
|
||||||
GraphicCard.t: 2,
|
|
||||||
Motherboard.t: 1,
|
|
||||||
NetworkAdapter.t: 2,
|
|
||||||
SoundCard.t: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, device: Device) -> None:
|
|
||||||
super().__init__()
|
|
||||||
self.device = device
|
|
||||||
# General information about device
|
|
||||||
self['Type'] = device.t
|
|
||||||
if isinstance(device, Computer):
|
|
||||||
self['Chassis'] = device.chassis
|
|
||||||
self['Tag 1'] = self['Tag 2'] = self['Tag 3'] = ''
|
|
||||||
for i, tag in zip(range(1, 3), device.tags):
|
|
||||||
self['Tag {}'.format(i)] = format(tag)
|
|
||||||
self['Serial Number'] = device.serial_number
|
|
||||||
self['Model'] = device.model
|
|
||||||
self['Manufacturer'] = device.manufacturer
|
|
||||||
# self['State'] = device.last_event_of()
|
|
||||||
self['Price'] = device.price
|
|
||||||
self['Registered in'] = format(device.created, '%c')
|
|
||||||
if isinstance(device, Computer):
|
|
||||||
self['Processor'] = device.processor_model
|
|
||||||
self['RAM (GB)'] = device.ram_size
|
|
||||||
self['Storage Size (MB)'] = device.data_storage_size
|
|
||||||
rate = device.rate
|
|
||||||
if rate:
|
|
||||||
self['Rate'] = rate.rating
|
|
||||||
self['Range'] = rate.rating_range
|
|
||||||
self['Processor Rate'] = rate.processor
|
|
||||||
self['Processor Range'] = rate.workbench.processor_range
|
|
||||||
self['RAM Rate'] = rate.ram
|
|
||||||
self['RAM Range'] = rate.workbench.ram_range
|
|
||||||
self['Data Storage Rate'] = rate.data_storage
|
|
||||||
self['Data Storage Range'] = rate.workbench.data_storage_range
|
|
||||||
# More specific information about components
|
|
||||||
if isinstance(device, Computer):
|
|
||||||
self.components()
|
|
||||||
|
|
||||||
|
|
||||||
def components(self):
|
|
||||||
"""
|
|
||||||
Function to get all components information of a device
|
|
||||||
"""
|
|
||||||
assert isinstance(self.device, Computer)
|
|
||||||
# todo put an input specific order (non alphabetic)
|
|
||||||
for type in sorted(app.resources[Component.t].subresources_types): # type: str
|
|
||||||
max = self.NUMS.get(type, 4)
|
|
||||||
if type not in ['Component', 'HardDrive', 'SolidStateDrive']:
|
|
||||||
i = 1
|
|
||||||
for component in (r for r in self.device.components if r.type == type):
|
|
||||||
self.fill_component(type, i, component)
|
|
||||||
i += 1
|
|
||||||
if i > max:
|
|
||||||
break
|
|
||||||
while i <= max:
|
|
||||||
self.fill_component(type, i)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
def fill_component(self, type, i, component=None):
|
|
||||||
"""
|
|
||||||
Function to put specific information of components in OrderedDict (csv)
|
|
||||||
:param type: type of component
|
|
||||||
:param component: device.components
|
|
||||||
"""
|
|
||||||
self['{} {}'.format(type, i)] = format(component) if component else ''
|
|
||||||
self['{} {} Manufacturer'.format(type, i)] = component.serial_number if component else ''
|
|
||||||
self['{} {} Model'.format(type, i)] = component.serial_number if component else ''
|
|
||||||
self['{} {} Serial Number'.format(type, i)] = component.serial_number if component else ''
|
|
||||||
|
|
||||||
""" Particular fields for component GraphicCard """
|
|
||||||
if isinstance(component, GraphicCard):
|
|
||||||
self['{} {} Memory (MB)'.format(type, i)] = component.memory
|
|
||||||
|
|
||||||
""" Particular fields for component DataStorage.t -> (HardDrive, SolidStateDrive) """
|
|
||||||
if isinstance(component, DataStorage):
|
|
||||||
self['{} {} Size (MB)'.format(type, i)] = component.size
|
|
||||||
self['{} {} Privacy'.format(type, i)] = component.privacy
|
|
||||||
|
|
||||||
# todo decide if is relevant more info about Motherboard
|
|
||||||
""" Particular fields for component Motherboard """
|
|
||||||
if isinstance(component, Motherboard):
|
|
||||||
self['{} {} Slots'.format(type, i)] = component.slots
|
|
||||||
|
|
||||||
""" Particular fields for component Processor """
|
|
||||||
if isinstance(component, Processor):
|
|
||||||
self['{} {} Number of cores'.format(type, i)] = component.cores
|
|
||||||
self['{} {} Speed (GHz)'.format(type, i)] = component.speed
|
|
||||||
|
|
||||||
""" Particular fields for component RamModule """
|
|
||||||
if isinstance(component, RamModule):
|
|
||||||
self['{} {} Size (MB)'.format(type, i)] = component.size
|
|
||||||
self['{} {} Speed (MHz)'.format(type, i)] = component.speed
|
|
||||||
self['{} {} Size'.format(type, i)] = component.size
|
|
||||||
|
|
||||||
# todo add Display size, ...
|
|
||||||
# todo add NetworkAdapter speedLink?
|
|
||||||
# todo add some ComputerAccessories
|
|
||||||
|
|
||||||
|
|
||||||
class ManufacturerView(View):
|
class ManufacturerView(View):
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from ereuse_devicehub.resources.device import models as d
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceRow(OrderedDict):
|
||||||
|
NUMS = {
|
||||||
|
d.Display.t: 1,
|
||||||
|
d.Processor.t: 2,
|
||||||
|
d.GraphicCard.t: 2,
|
||||||
|
d.Motherboard.t: 1,
|
||||||
|
d.NetworkAdapter.t: 2,
|
||||||
|
d.SoundCard.t: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, device: d.Device) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.device = device
|
||||||
|
# General information about device
|
||||||
|
self['Type'] = device.t
|
||||||
|
if isinstance(device, d.Computer):
|
||||||
|
self['Chassis'] = device.chassis
|
||||||
|
self['Tag 1'] = self['Tag 2'] = self['Tag 3'] = ''
|
||||||
|
for i, tag in zip(range(1, 3), device.tags):
|
||||||
|
self['Tag {}'.format(i)] = format(tag)
|
||||||
|
self['Serial Number'] = device.serial_number
|
||||||
|
self['Model'] = device.model
|
||||||
|
self['Manufacturer'] = device.manufacturer
|
||||||
|
# self['State'] = device.last_event_of()
|
||||||
|
self['Price'] = device.price
|
||||||
|
self['Registered in'] = format(device.created, '%c')
|
||||||
|
if isinstance(device, d.Computer):
|
||||||
|
self['Processor'] = device.processor_model
|
||||||
|
self['RAM (GB)'] = device.ram_size
|
||||||
|
self['Storage Size (MB)'] = device.data_storage_size
|
||||||
|
rate = device.rate
|
||||||
|
if rate:
|
||||||
|
self['Rate'] = rate.rating
|
||||||
|
self['Range'] = rate.rating_range
|
||||||
|
self['Processor Rate'] = rate.processor
|
||||||
|
self['Processor Range'] = rate.workbench.processor_range
|
||||||
|
self['RAM Rate'] = rate.ram
|
||||||
|
self['RAM Range'] = rate.workbench.ram_range
|
||||||
|
self['Data Storage Rate'] = rate.data_storage
|
||||||
|
self['Data Storage Range'] = rate.workbench.data_storage_range
|
||||||
|
# More specific information about components
|
||||||
|
if isinstance(device, d.Computer):
|
||||||
|
self.components()
|
||||||
|
|
||||||
|
def components(self):
|
||||||
|
"""
|
||||||
|
Function to get all components information of a device
|
||||||
|
"""
|
||||||
|
assert isinstance(self.device, d.Computer)
|
||||||
|
# todo put an input specific order (non alphabetic)
|
||||||
|
for type in sorted(current_app.resources[d.Component.t].subresources_types): # type: str
|
||||||
|
max = self.NUMS.get(type, 4)
|
||||||
|
if type not in ['Component', 'HardDrive', 'SolidStateDrive']:
|
||||||
|
i = 1
|
||||||
|
for component in (r for r in self.device.components if r.type == type):
|
||||||
|
self.fill_component(type, i, component)
|
||||||
|
i += 1
|
||||||
|
if i > max:
|
||||||
|
break
|
||||||
|
while i <= max:
|
||||||
|
self.fill_component(type, i)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def fill_component(self, type, i, component=None):
|
||||||
|
"""
|
||||||
|
Function to put specific information of components in OrderedDict (csv)
|
||||||
|
:param type: type of component
|
||||||
|
:param component: device.components
|
||||||
|
"""
|
||||||
|
self['{} {}'.format(type, i)] = format(component) if component else ''
|
||||||
|
self['{} {} Manufacturer'.format(type, i)] = component.serial_number if component else ''
|
||||||
|
self['{} {} Model'.format(type, i)] = component.serial_number if component else ''
|
||||||
|
self['{} {} Serial Number'.format(type, i)] = component.serial_number if component else ''
|
||||||
|
|
||||||
|
""" Particular fields for component GraphicCard """
|
||||||
|
if isinstance(component, d.GraphicCard):
|
||||||
|
self['{} {} Memory (MB)'.format(type, i)] = component.memory
|
||||||
|
|
||||||
|
""" Particular fields for component DataStorage.t -> (HardDrive, SolidStateDrive) """
|
||||||
|
if isinstance(component, d.DataStorage):
|
||||||
|
self['{} {} Size (MB)'.format(type, i)] = component.size
|
||||||
|
self['{} {} Privacy'.format(type, i)] = component.privacy
|
||||||
|
|
||||||
|
# todo decide if is relevant more info about Motherboard
|
||||||
|
""" Particular fields for component Motherboard """
|
||||||
|
if isinstance(component, d.Motherboard):
|
||||||
|
self['{} {} Slots'.format(type, i)] = component.slots
|
||||||
|
|
||||||
|
""" Particular fields for component Processor """
|
||||||
|
if isinstance(component, d.Processor):
|
||||||
|
self['{} {} Number of cores'.format(type, i)] = component.cores
|
||||||
|
self['{} {} Speed (GHz)'.format(type, i)] = component.speed
|
||||||
|
|
||||||
|
""" Particular fields for component RamModule """
|
||||||
|
if isinstance(component, d.RamModule):
|
||||||
|
self['{} {} Size (MB)'.format(type, i)] = component.size
|
||||||
|
self['{} {} Speed (MHz)'.format(type, i)] = component.speed
|
||||||
|
self['{} {} Size'.format(type, i)] = component.size
|
||||||
|
|
||||||
|
# todo add Display size, ...
|
||||||
|
# todo add NetworkAdapter speedLink?
|
||||||
|
# todo add some ComputerAccessories
|
|
@ -1,5 +1,8 @@
|
||||||
|
import csv
|
||||||
|
import datetime
|
||||||
import enum
|
import enum
|
||||||
import uuid
|
import uuid
|
||||||
|
from io import StringIO
|
||||||
from typing import Callable, Iterable, Tuple
|
from typing import Callable, Iterable, Tuple
|
||||||
|
|
||||||
import boltons
|
import boltons
|
||||||
|
@ -7,11 +10,14 @@ import flask
|
||||||
import flask_weasyprint
|
import flask_weasyprint
|
||||||
import teal.marshmallow
|
import teal.marshmallow
|
||||||
from boltons import urlutils
|
from boltons import urlutils
|
||||||
|
from flask import make_response
|
||||||
|
from teal.cache import cache
|
||||||
from teal.resource import Resource
|
from teal.resource import Resource
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.device import models as devs
|
from ereuse_devicehub.resources.device import models as devs
|
||||||
from ereuse_devicehub.resources.device.views import DeviceView
|
from ereuse_devicehub.resources.device.views import DeviceView
|
||||||
|
from ereuse_devicehub.resources.documents.device_row import DeviceRow
|
||||||
from ereuse_devicehub.resources.event import models as evs
|
from ereuse_devicehub.resources.event import models as evs
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +103,33 @@ class DocumentView(DeviceView):
|
||||||
return flask.render_template('documents/erasure.html', **params)
|
return flask.render_template('documents/erasure.html', **params)
|
||||||
|
|
||||||
|
|
||||||
|
class DevicesDocumentView(DeviceView):
|
||||||
|
@cache(datetime.timedelta(minutes=1))
|
||||||
|
def find(self, args: dict):
|
||||||
|
query = self.query(args)
|
||||||
|
return self.generate_post_csv(query)
|
||||||
|
|
||||||
|
def generate_post_csv(self, query):
|
||||||
|
"""
|
||||||
|
Get device query and put information in csv format
|
||||||
|
:param query:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
data = StringIO()
|
||||||
|
cw = csv.writer(data)
|
||||||
|
first = True
|
||||||
|
for device in query:
|
||||||
|
d = DeviceRow(device)
|
||||||
|
if first:
|
||||||
|
cw.writerow(name for name in d.keys())
|
||||||
|
first = False
|
||||||
|
cw.writerow(v for v in d.values())
|
||||||
|
output = make_response(data.getvalue())
|
||||||
|
output.headers['Content-Disposition'] = 'attachment; filename=export.csv'
|
||||||
|
output.headers['Content-type'] = 'text/csv'
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
class DocumentDef(Resource):
|
class DocumentDef(Resource):
|
||||||
__type__ = 'Document'
|
__type__ = 'Document'
|
||||||
SCHEMA = None
|
SCHEMA = None
|
||||||
|
@ -124,3 +157,9 @@ class DocumentDef(Resource):
|
||||||
self.add_url_rule('/erasures/', defaults=d, view_func=view, methods=get)
|
self.add_url_rule('/erasures/', defaults=d, view_func=view, methods=get)
|
||||||
self.add_url_rule('/erasures/<{}:{}>'.format(self.ID_CONVERTER.value, self.ID_NAME),
|
self.add_url_rule('/erasures/<{}:{}>'.format(self.ID_CONVERTER.value, self.ID_NAME),
|
||||||
view_func=view, methods=get)
|
view_func=view, methods=get)
|
||||||
|
devices_view = DevicesDocumentView.as_view('devicesDocumentView',
|
||||||
|
definition=self,
|
||||||
|
auth=app.auth)
|
||||||
|
if self.AUTH:
|
||||||
|
devices_view = app.auth.requires_auth(devices_view)
|
||||||
|
self.add_url_rule('/devices/', defaults=d, view_func=devices_view, methods=get)
|
||||||
|
|
|
@ -28,6 +28,7 @@ def test_api_docs(client: Client):
|
||||||
'/lots/{id}/children',
|
'/lots/{id}/children',
|
||||||
'/lots/{id}/devices',
|
'/lots/{id}/devices',
|
||||||
'/documents/erasures/',
|
'/documents/erasures/',
|
||||||
|
'/documents/devices/',
|
||||||
'/documents/static/{filename}',
|
'/documents/static/{filename}',
|
||||||
'/tags/{tag_id}/device/{device_id}',
|
'/tags/{tag_id}/device/{device_id}',
|
||||||
'/devices/static/{filename}'
|
'/devices/static/{filename}'
|
||||||
|
|
|
@ -3,8 +3,10 @@ from datetime import datetime
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from ereuse_devicehub.client import UserClient
|
from ereuse_devicehub.client import UserClient
|
||||||
from ereuse_devicehub.resources.device.models import Device
|
from ereuse_devicehub.resources.documents import documents as docs
|
||||||
from ereuse_devicehub.resources.event.models import Snapshot
|
from ereuse_devicehub.resources.event.models import Snapshot
|
||||||
from tests.conftest import file
|
from tests.conftest import file
|
||||||
|
|
||||||
|
@ -14,7 +16,8 @@ def test_export_basic_snapshot(user: UserClient):
|
||||||
Test export device information in a csv file
|
Test export device information in a csv file
|
||||||
"""
|
"""
|
||||||
snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot)
|
snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot)
|
||||||
csv_str, _ = user.get(res=Device,
|
csv_str, _ = user.get(res=docs.DocumentDef.t,
|
||||||
|
item='devices/',
|
||||||
accept='text/csv',
|
accept='text/csv',
|
||||||
query=[('filter', {'type': ['Computer']})])
|
query=[('filter', {'type': ['Computer']})])
|
||||||
f = StringIO(csv_str)
|
f = StringIO(csv_str)
|
||||||
|
@ -40,7 +43,8 @@ def test_export_full_snapshot(user: UserClient):
|
||||||
Test a export device with all information and a lot of components
|
Test a export device with all information and a lot of components
|
||||||
"""
|
"""
|
||||||
snapshot, _ = user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot)
|
snapshot, _ = user.post(file('real-eee-1001pxd.snapshot.11'), res=Snapshot)
|
||||||
csv_str, _ = user.get(res=Device,
|
csv_str, _ = user.get(res=docs.DocumentDef.t,
|
||||||
|
item='devices/',
|
||||||
accept='text/csv',
|
accept='text/csv',
|
||||||
query=[('filter', {'type': ['Computer']})])
|
query=[('filter', {'type': ['Computer']})])
|
||||||
f = StringIO(csv_str)
|
f = StringIO(csv_str)
|
||||||
|
@ -67,7 +71,9 @@ def test_export_empty(user: UserClient):
|
||||||
"""
|
"""
|
||||||
Test to check works correctly exporting csv without any information (no snapshot)
|
Test to check works correctly exporting csv without any information (no snapshot)
|
||||||
"""
|
"""
|
||||||
csv_str, _ = user.get(res=Device, accept='text/csv')
|
csv_str, _ = user.get(res=docs.DocumentDef.t,
|
||||||
|
accept='text/csv',
|
||||||
|
item='devices/')
|
||||||
f = StringIO(csv_str)
|
f = StringIO(csv_str)
|
||||||
obj_csv = csv.reader(f, f)
|
obj_csv = csv.reader(f, f)
|
||||||
export_csv = list(obj_csv)
|
export_csv = list(obj_csv)
|
||||||
|
@ -80,7 +86,8 @@ def test_export_computer_monitor(user: UserClient):
|
||||||
Test a export device type computer monitor
|
Test a export device type computer monitor
|
||||||
"""
|
"""
|
||||||
snapshot, _ = user.post(file('computer-monitor.snapshot'), res=Snapshot)
|
snapshot, _ = user.post(file('computer-monitor.snapshot'), res=Snapshot)
|
||||||
csv_str, _ = user.get(res=Device,
|
csv_str, _ = user.get(res=docs.DocumentDef.t,
|
||||||
|
item='devices/',
|
||||||
accept='text/csv',
|
accept='text/csv',
|
||||||
query=[('filter', {'type': ['ComputerMonitor']})])
|
query=[('filter', {'type': ['ComputerMonitor']})])
|
||||||
f = StringIO(csv_str)
|
f = StringIO(csv_str)
|
||||||
|
@ -105,7 +112,8 @@ def test_export_keyboard(user: UserClient):
|
||||||
Test a export device type keyboard
|
Test a export device type keyboard
|
||||||
"""
|
"""
|
||||||
snapshot, _ = user.post(file('keyboard.snapshot'), res=Snapshot)
|
snapshot, _ = user.post(file('keyboard.snapshot'), res=Snapshot)
|
||||||
csv_str, _ = user.get(res=Device,
|
csv_str, _ = user.get(res=docs.DocumentDef.t,
|
||||||
|
item='devices/',
|
||||||
accept='text/csv',
|
accept='text/csv',
|
||||||
query=[('filter', {'type': ['Keyboard']})])
|
query=[('filter', {'type': ['Keyboard']})])
|
||||||
f = StringIO(csv_str)
|
f = StringIO(csv_str)
|
||||||
|
@ -124,6 +132,7 @@ def test_export_keyboard(user: UserClient):
|
||||||
assert fixture_csv[1] == export_csv[1], 'Component information are not equal'
|
assert fixture_csv[1] == export_csv[1], 'Component information are not equal'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.xfail(reason='Develop test')
|
||||||
def test_export_multiple_devices(user: UserClient):
|
def test_export_multiple_devices(user: UserClient):
|
||||||
"""
|
"""
|
||||||
Test a export multiple devices with different components and information
|
Test a export multiple devices with different components and information
|
||||||
|
@ -131,6 +140,7 @@ def test_export_multiple_devices(user: UserClient):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.xfail(reason='Develop test')
|
||||||
def test_export_only_components(user: UserClient):
|
def test_export_only_components(user: UserClient):
|
||||||
"""
|
"""
|
||||||
Test a export only components
|
Test a export only components
|
||||||
|
@ -138,7 +148,8 @@ def test_export_only_components(user: UserClient):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_export_computers__and_components(user: UserClient):
|
@pytest.mark.xfail(reason='Develop test')
|
||||||
|
def test_export_computers_and_components(user: UserClient):
|
||||||
"""
|
"""
|
||||||
Test a export multiple devices (computers and independent components)
|
Test a export multiple devices (computers and independent components)
|
||||||
"""
|
"""
|
||||||
|
|
Reference in New Issue