def test_init_db(db: SQLAlchemy, config: Config): """Tests :meth:`teal.resource.Resource.init_db` with one inventory.""" class Foo(db.Model): id = Column(db.Integer, primary_key=True) class FooDef(Resource): __type__ = 'Foo' def init_db(self, db: SQLAlchemy, exclude_schema=None): db.session.add(Foo()) config.RESOURCE_DEFINITIONS = FooDef, app = Teal(config=config, db=db) with app.app_context(): app.init_db() with app.app_context(): # If no commit happened in init_db() or anything else # this would not exist assert Foo.query.filter_by(id=1).one() # Test again but executing init-db through the command-line runner = app.test_cli_runner() runner.invoke('init-db') with app.app_context(): assert Foo.query.filter_by(id=2).one() # Test with --erase option runner.invoke('init-db', '--erase') with app.app_context(): assert Foo.query.count() == 1
def test_etag_secondary(client: Client, app: Teal): """Tests creating, linking and accessing an ETag through its secondary (NFC) id.""" with app.app_context(): et = ETag(secondary='NFCID') db.session.add(et) db.session.commit() client.get('/', item='NFCID', accept=ANY, status=400) with app.app_context(): tag = ETag.query.filter_by(secondary='NFCID').one() tag.devicehub = URL('https://dh.com') db.session.commit() _, r = client.get('/', item='NFCID', accept=ANY, status=302) assert r.location == 'https://dh.com/tags/FO-3MP5M/device'
def test_tag_export(runner: FlaskCliRunner, app: Teal): with app.app_context(): t = ETag() db.session.add(t) db.session.commit() with NamedTemporaryFile('r+') as f: result = runner.invoke(args=('export', f.name), catch_exceptions=False) assert result.exit_code == 0 result = runner.invoke(args=('import', f.name), catch_exceptions=False) assert result.exit_code == 0 with app.app_context(): t = Tag() db.session.add(t) db.session.commit() assert Tag.decode(t.id) == 2
def test_json_encoder(app: Teal): """ Ensures that Teal is using the custom JSON Encoder through Flask's json. """ with app.app_context(): # Try to dump a type flask's json encoder cannot handle json.dumps({'foo': StrictVersion('1.3')})
def test_get_not_linked_tag(app: Teal, client: Client): """Tests getting a tag that has not been linked yet to a Devicehub.""" with app.app_context(): t = Tag() db.session.add(t) db.session.commit() id = t.id client.get(res=Tag.t, item=id, status=NoRemoteTag)
def test_not_found(app: Teal): """ When not finding a resource, the db should raise a ``NotFound`` exception instead of the built-in for SQLAlchemy. """ with app.app_context(): Device = app.resources['Device'].MODEL with pytest.raises(NotFound): Device.query.one()
def test_validator_is_type(app: Teal): """Checks the validator IsType""" with app.app_context(): is_type = IsType() is_type('Device') is_type('Component') with pytest.raises(ValidationError): is_type('Foo') is_subtype = IsType('Component') is_subtype('Component') with pytest.raises(ValidationError): is_subtype('Computer')
def test_models(app: Teal, db: SQLAlchemy): """Checks that the models used in the fixture work.""" DeviceDef, ComponentDef, ComputerDef = \ app.config['RESOURCE_DEFINITIONS'] # type: Tuple[ResourceDef] Component = ComponentDef.MODEL Computer = ComputerDef.MODEL component = Component(id=1, model='foo') pc = Computer(id=2, model='bar', components=[component]) with app.app_context(): db.session.add(pc) queried_pc = Computer.query.first() assert pc == queried_pc
def test_nested_on(fconfig: Config, db: SQLAlchemy): """Tests the NestedOn marshmallow field.""" DeviceDef, ComponentDef, ComputerDef = fconfig.RESOURCE_DEFINITIONS class GraphicCardSchema(ComponentDef.SCHEMA): speed = Integer() class GraphicCard(ComponentDef.MODEL): speed = db.Column(db.Integer) class GraphicCardDef(ComponentDef): SCHEMA = GraphicCardSchema MODEL = GraphicCard fconfig.RESOURCE_DEFINITIONS += (GraphicCardDef,) app = Teal(config=fconfig, db=db) pc_template = { 'id': 1, 'components': [ {'id': 2, 'type': 'Component'}, {'id': 3, 'type': 'GraphicCard', 'speed': 4} ] } with app.app_context(): schema = app.resources['Computer'].SCHEMA() result = schema.load(pc_template) assert pc_template['id'] == result['id'] assert isinstance(result['components'][0], ComponentDef.MODEL) assert isinstance(result['components'][1], GraphicCardDef.MODEL) # Let's add the graphic card's speed field to the component with pytest.raises(ValidationError, message={'components': {'speed': ['Unknown field']}}): pc = deepcopy(pc_template) pc['components'][0]['speed'] = 4 schema.load(pc) # Let's remove the 'type' with pytest.raises(ValidationError, message={ 'components': ['\'Type\' field required to disambiguate resources.'] }): pc = deepcopy(pc_template) del pc['components'][0]['type'] del pc['components'][1]['type'] schema.load(pc) # Let's set a 'type' that is not a Component with pytest.raises(ValidationError, message={'components': ['Computer is not a sub-type of Component']}): pc = deepcopy(pc_template) pc['components'][0]['type'] = 'Computer' schema.load(pc)
def test_tag_creation(app: Teal): with app.app_context(): t = Tag() db.session.add(t) db.session.commit() assert t.id assert t.devicehub is None assert t.id == '3MP5M' et = ETag() db.session.add(et) db.session.commit() assert et.id == 'FO-WNBRM' assert et.id.split('-')[0] == 'FO' assert len(et.id.split('-')[1]) == 5 assert et.devicehub is None
def test_query_sort(app: Teal): """Tests sorting params.""" with app.app_context(): Device = app.resources['Device'].MODEL class Sorting(Sort): models = SortField(Device.model) ids = SortField(Device.id) schema = Sorting() sort = tuple( str(s) for s in schema.load({ 'models': True, 'ids': False })) assert len(sort) == 2 assert 'device.model ASC' in sort assert 'device.id DESC' in sort
def test_query_join(app: Teal): """Checks that nested queries work.""" with app.app_context(): Device = app.resources['Device'].MODEL Computer = app.resources['Computer'].MODEL class Inner(Query): foo = ILike(Device.model) class Q(Query): idq = Between(Device.id, Integer()) componentq = Join(Device.id == Computer.id, Inner) schema = Q() query = schema.load({'idq': [1, 4], 'componentq': {'foo': 'bar'}}) s, params = compiled(Device, query) assert 'device.id BETWEEN %(id_1)s AND %(id_2)s' in s assert 'device.model ILIKE %(model_1)s' in s assert params == {'id_1': 1, 'model_1': 'bar%', 'id_2': 4}
def test_query(app: Teal): with app.app_context(): Device = app.resources['Device'].MODEL class Q(Query): idq = Or(Equal(Device.id, Str())) modelq = ILike(Device.model) schema = Q() query = schema.load({'idq': ['a', 'b', 'c'], 'modelq': 'foobar'}) s, params = compiled(Device, query) # Order between query clauses can change assert 'device.model ILIKE %(model_1)s' in s assert '(device.id = %(id_1)s OR device.id = %(id_2)s OR device.id = %(id_3)s' in s assert params == { 'id_2': 'b', 'id_3': 'c', 'id_1': 'a', 'model_1': 'foobar%' }
def app_context(app: Teal): with app.app_context(): yield
def app(fconfig: Config, db: SQLAlchemy) -> Teal: app = Teal(config=fconfig, db=db) with app.app_context(): app.init_db() yield app