diff --git a/rattail/db/model/stores.py b/rattail/db/model/stores.py index 769e3093b95f311e377c3bbdb7a2be074baef479..d5356df99ef73d5ef5de6526d4b9668cae1a19a6 100644 --- a/rattail/db/model/stores.py +++ b/rattail/db/model/stores.py @@ -74,6 +74,11 @@ class Store(Base): phone = StorePhoneNumber(number=number, type=type) self.phones.append(phone) + # TODO: this class should use ContactMixin instead + def first_phone(self, **kwargs): + if self.phones: + return self.phones[0] + class StorePhoneNumber(PhoneNumber): """ diff --git a/tests/autocomplete/__init__.py b/tests/autocomplete/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/autocomplete/test_base.py b/tests/autocomplete/test_base.py new file mode 100644 index 0000000000000000000000000000000000000000..b696c77cc9b0545d9de69870e1fe0e275348ffe5 --- /dev/null +++ b/tests/autocomplete/test_base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import base as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + + def make_config(self): + return make_config([], extend=False) + + def test_constructor(self): + + # cannot instantiate autocompleter with no key + class BadAutocompleter(mod.Autocompleter): + pass + self.assertRaises(NotImplementedError, BadAutocompleter, self.config) + + # but works okay if key is defined + class GoodAutocompleter(mod.Autocompleter): + autocompleter_key = 'stores' + autocompleter = GoodAutocompleter(self.config) + self.assertIsNotNone(autocompleter) + + def test_get_model_class(self): + model = self.config.get_model() + + # no model class by default; hence error + class BadAutocompleter(mod.Autocompleter): + autocompleter_key = 'stores' + autocompleter = BadAutocompleter(self.config) + self.assertRaises(AttributeError, autocompleter.get_model_class) + + # but if one is set, it is returned + class GoodAutocompleter(mod.Autocompleter): + autocompleter_key = 'stores' + model_class = model.Store + autocompleter = GoodAutocompleter(self.config) + result = autocompleter.get_model_class() + self.assertIs(result, model.Store) + + def test_autocomplete_fieldname(self): + + # no fieldname by default; hence error + class BadAutocompleter(mod.Autocompleter): + autocompleter_key = 'stores' + autocompleter = BadAutocompleter(self.config) + self.assertRaises(NotImplementedError, getattr, + autocompleter, 'autocomplete_fieldname') + + # but works okay if class defines it + class GoodAutocompleter(mod.Autocompleter): + autocompleter_key = 'stores' + autocomplete_fieldname = 'name' + autocompleter = GoodAutocompleter(self.config) + self.assertEqual(autocompleter.autocomplete_fieldname, 'name') + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + + class StoreAutocompleter(mod.Autocompleter): + autocompleter_key = 'store' + model_class = model.Store + autocomplete_fieldname = 'name' + + # first create a few stores + store001 = model.Store(id='001', name="Acme Store #1") + session.add(store001) + store002 = model.Store(id='002', name="Acme Store #2") + session.add(store002) + store999 = model.Store(id='999', name="Warehouse") + session.add(store999) + + # and our autocompleter + autocompleter = StoreAutocompleter(self.config) + + # searching for nothing yields no results + result = autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'acme' yields stores 1, 2 + result = autocompleter.autocomplete(session, 'acme') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(store001.uuid, uuids) + self.assertIn(store002.uuid, uuids) + + # search for 'warehouse' yields store 999 + result = autocompleter.autocomplete(session, 'warehouse') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], store999.uuid) + + # search for 'bogus' yields no results + result = autocompleter.autocomplete(session, 'bogus') + self.assertEqual(len(result), 0) + + # search for 's' yields all 3 stores + result = autocompleter.autocomplete(session, 's') + self.assertEqual(len(result), 3) + + # unless we cap the max results + autocompleter.max_results = 2 + result = autocompleter.autocomplete(session, 's') + self.assertEqual(len(result), 2) + + # removing cap should get all 3 again + autocompleter.max_results = None + result = autocompleter.autocomplete(session, 's') + self.assertEqual(len(result), 3) + + +class TestPhoneMagicMixin(TestCase): + + def setUp(self): + self.config = self.make_config() + + def make_config(self): + return make_config([], extend=False) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + + class StoreMagicAutocompleter(mod.PhoneMagicMixin, mod.Autocompleter): + autocompleter_key = 'store' + model_class = model.Store + autocomplete_fieldname = 'name' + phone_model_class = model.StorePhoneNumber + + # first create a few stores, with phones + store001 = model.Store(id='001', name="Acme Store #1") + store001.add_phone_number('417-555-0001') + session.add(store001) + store002 = model.Store(id='002', name="Acme Store #2") + store002.add_phone_number('417-555-0002') + session.add(store002) + store999 = model.Store(id='999', name="Warehouse") + session.add(store999) + + # and our autocompleter + autocompleter = StoreMagicAutocompleter(self.config) + + # searching for nothing yields no results + result = autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'acme' yields stores 1, 2 + result = autocompleter.autocomplete(session, 'acme') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(store001.uuid, uuids) + self.assertIn(store002.uuid, uuids) + + # search for 'warehouse' yields store 999 + result = autocompleter.autocomplete(session, 'warehouse') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], store999.uuid) + + # TODO: need to test the actual phone number magic, but sqlite + # does not have a regexp_replace() function built-in. so + # either need to code some workaround, or require the 're' + # extension be loaded for sqlite, etc. diff --git a/tests/autocomplete/test_brands.py b/tests/autocomplete/test_brands.py new file mode 100644 index 0000000000000000000000000000000000000000..536f98b035c66f165c027370883c3fdba964933b --- /dev/null +++ b/tests/autocomplete/test_brands.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import brands as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestBrandAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.BrandAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + + # first create a few brands + alpha = model.Brand(name='Alpha Natural Foods') + session.add(alpha) + beta = model.Brand(name='Beta Natural Foods') + session.add(beta) + gamma = model.Brand(name='Gamma Natural Foods') + session.add(gamma) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'natural' yields all 3 brands + result = self.autocompleter.autocomplete(session, 'natural') + self.assertEqual(len(result), 3) + + # search for 'gamma' yields just that brand + result = self.autocompleter.autocomplete(session, 'gamma') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], gamma.uuid) diff --git a/tests/autocomplete/test_customers.py b/tests/autocomplete/test_customers.py new file mode 100644 index 0000000000000000000000000000000000000000..48cf9c3b7dbf7b4a17da7294cd3805c6494d942b --- /dev/null +++ b/tests/autocomplete/test_customers.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import customers as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestCustomerAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.CustomerAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + enum = self.config.get_enum() + + # first create some customers + alice = model.Customer(name='Alice Chalmers') + session.add(alice) + bob = model.Customer(name='Bob Loblaw') + session.add(bob) + charlie = model.Customer(name='Charlie Chaplin') + session.add(charlie) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'l' yields all 3 customers + result = self.autocompleter.autocomplete(session, 'l') + self.assertEqual(len(result), 3) + + # search for 'cha' yields just 2 customers + result = self.autocompleter.autocomplete(session, 'cha') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(alice.uuid, uuids) + self.assertIn(charlie.uuid, uuids) diff --git a/tests/autocomplete/test_departments.py b/tests/autocomplete/test_departments.py new file mode 100644 index 0000000000000000000000000000000000000000..bb03980cb38b7f4313d226a020a417569dd230a0 --- /dev/null +++ b/tests/autocomplete/test_departments.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import departments as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestDepartmentAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.DepartmentAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + + # first create a few departments + grocery = model.Department(name='Grocery') + session.add(grocery) + wellness = model.Department(name='Wellness') + session.add(wellness) + bulk = model.Department(name='Bulk') + session.add(bulk) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'l' yields Wellness, Bulk + result = self.autocompleter.autocomplete(session, 'l') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(wellness.uuid, uuids) + self.assertIn(bulk.uuid, uuids) + + # search for 'grocery' yields just that department + result = self.autocompleter.autocomplete(session, 'grocery') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], grocery.uuid) diff --git a/tests/autocomplete/test_employees.py b/tests/autocomplete/test_employees.py new file mode 100644 index 0000000000000000000000000000000000000000..382aeaad47b736f92e50bdbe7ee36bb5deab421c --- /dev/null +++ b/tests/autocomplete/test_employees.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import employees as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestEmployeeAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.EmployeeAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + enum = self.config.get_enum() + + # first create some employees + alice = model.Person(display_name='Alice Chalmers') + alice.employee = model.Employee(status=enum.EMPLOYEE_STATUS_CURRENT) + session.add(alice) + bob = model.Person(display_name='Bob Loblaw') + bob.employee = model.Employee(status=enum.EMPLOYEE_STATUS_CURRENT) + session.add(bob) + charlie = model.Person(display_name='Charlie Chaplin') + charlie.employee = model.Employee(status=enum.EMPLOYEE_STATUS_FORMER) + session.add(charlie) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'l' yields only 2 current employees + result = self.autocompleter.autocomplete(session, 'l') + self.assertEqual(len(result), 2) + + # search for 'alice' yields just Alice Chalmers + result = self.autocompleter.autocomplete(session, 'alice') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], alice.employee.uuid) diff --git a/tests/autocomplete/test_people.py b/tests/autocomplete/test_people.py new file mode 100644 index 0000000000000000000000000000000000000000..fcb6400f477d961bdb4fde7b761293ae00340019 --- /dev/null +++ b/tests/autocomplete/test_people.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import people as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestPersonAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.PersonAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + enum = self.config.get_enum() + + # first create some people + alice = model.Person(display_name='Alice Chalmers') + session.add(alice) + bob = model.Person(display_name='Bob Loblaw') + session.add(bob) + charlie = model.Person(display_name='Charlie Chaplin') + session.add(charlie) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'l' yields all 3 people + result = self.autocompleter.autocomplete(session, 'l') + self.assertEqual(len(result), 3) + + # search for 'cha' yields just 2 people + result = self.autocompleter.autocomplete(session, 'cha') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(alice.uuid, uuids) + self.assertIn(charlie.uuid, uuids) + + +class TestPersonEmployeeAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.PersonEmployeeAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + enum = self.config.get_enum() + + # first create some people + alice = model.Person(display_name='Alice Chalmers') + session.add(alice) + bob = model.Person(display_name='Bob Loblaw') + bob.employee = model.Employee(status=enum.EMPLOYEE_STATUS_CURRENT) + session.add(bob) + charlie = model.Person(display_name='Charlie Chaplin') + charlie.employee = model.Employee(status=enum.EMPLOYEE_STATUS_FORMER) + session.add(charlie) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'l' yields only Bob, Charlie + result = self.autocompleter.autocomplete(session, 'l') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(bob.uuid, uuids) + self.assertIn(charlie.uuid, uuids) + + # search for 'cha' yields just Charlie + result = self.autocompleter.autocomplete(session, 'cha') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], charlie.uuid) diff --git a/tests/autocomplete/test_products.py b/tests/autocomplete/test_products.py new file mode 100644 index 0000000000000000000000000000000000000000..d0eba740f8cd454319e0526d693ee895fa9f15a3 --- /dev/null +++ b/tests/autocomplete/test_products.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import products as mod +from rattail.config import make_config +from rattail.db import Session + + +class AutocompleterTestCase(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + self.engine = sa.create_engine('sqlite://') + self.model = self.config.get_model() + self.model.Base.metadata.create_all(bind=self.engine) + self.session = Session(bind=self.engine) + + def tearDown(self): + self.session.rollback() + self.session.close() + + def make_config(self): + return make_config([], extend=False) + + +class TestProductAutocompleter(AutocompleterTestCase): + + def make_autocompleter(self): + return mod.ProductAutocompleter(self.config) + + def test_autocomplete(self): + session = self.session + model = self.model + + # first create a few products + vinegar = model.Product(description='Apple Cider Vinegar') + session.add(vinegar) + dressing = model.Product(description='Apple Cider Dressing') + session.add(dressing) + oats = model.Product(description='Bulk Oats') + session.add(oats) + deleted = model.Product(description='More Oats', deleted=True) + session.add(deleted) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'apple' yields Vinegar, Dressing + result = self.autocompleter.autocomplete(session, 'apple') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(vinegar.uuid, uuids) + self.assertIn(dressing.uuid, uuids) + + # search for 'oats' yields just the undeleted product + result = self.autocompleter.autocomplete(session, 'oats') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], oats.uuid) + + +class TestProductAllAutocompleter(AutocompleterTestCase): + + def make_autocompleter(self): + return mod.ProductAllAutocompleter(self.config) + + def test_autocomplete(self): + session = self.session + model = self.model + + # first create a few products + vinegar = model.Product(description='Apple Cider Vinegar') + session.add(vinegar) + dressing = model.Product(description='Apple Cider Dressing') + session.add(dressing) + oats = model.Product(description='Bulk Oats') + session.add(oats) + deleted = model.Product(description='More Oats', deleted=True) + session.add(deleted) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'apple' yields Vinegar, Dressing + result = self.autocompleter.autocomplete(session, 'apple') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(vinegar.uuid, uuids) + self.assertIn(dressing.uuid, uuids) + + # search for 'oats' yields Bulk, More + result = self.autocompleter.autocomplete(session, 'oats') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(oats.uuid, uuids) + self.assertIn(deleted.uuid, uuids) + + +class TestProductNewOrderAutocompleter(AutocompleterTestCase): + + def make_autocompleter(self): + return mod.ProductNewOrderAutocompleter(self.config) + + def test_autocomplete(self): + session = self.session + model = self.model + + # first create a few products + vinegar = model.Product(description='Apple Cider Vinegar', + upc='074305001321') + session.add(vinegar) + dressing = model.Product(description='Apple Cider Dressing') + session.add(dressing) + oats = model.Product(description='Bulk Oats') + session.add(oats) + deleted = model.Product(description='More Oats', deleted=True) + session.add(deleted) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'apple' yields Vinegar, Dressing + result = self.autocompleter.autocomplete(session, 'apple') + self.assertEqual(len(result), 2) + uuids = [info['value'] for info in result] + self.assertIn(vinegar.uuid, uuids) + self.assertIn(dressing.uuid, uuids) + + # search for unknown upc yields no results + result = self.autocompleter.autocomplete(session, '7430500116') + self.assertEqual(len(result), 0) + + # search for known upc yields just that product + result = self.autocompleter.autocomplete(session, '7430500132') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], vinegar.uuid) + + # search for scancode yields no results + self.autocompleter.lookup_only_keys = ['scancode'] + result = self.autocompleter.autocomplete(session, '7430500132') + self.assertEqual(len(result), 0) diff --git a/tests/autocomplete/test_vendors.py b/tests/autocomplete/test_vendors.py new file mode 100644 index 0000000000000000000000000000000000000000..48ed4f0cc92c7e619133a0fe5cfb69dd8c47d66d --- /dev/null +++ b/tests/autocomplete/test_vendors.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8; -*- + +from __future__ import unicode_literals, absolute_import + +from unittest import TestCase + +import sqlalchemy as sa + +from rattail.autocomplete import vendors as mod +from rattail.config import make_config +from rattail.db import Session + + +class TestVendorAutocompleter(TestCase): + + def setUp(self): + self.config = self.make_config() + self.autocompleter = self.make_autocompleter() + + def make_config(self): + return make_config([], extend=False) + + def make_autocompleter(self): + return mod.VendorAutocompleter(self.config) + + def test_autocomplete(self): + engine = sa.create_engine('sqlite://') + model = self.config.get_model() + model.Base.metadata.create_all(bind=engine) + session = Session(bind=engine) + + # first create some vendors + acme = model.Vendor(name='Acme Wholesale Foods') + session.add(acme) + bigboy = model.Vendor(name='Big Boy Distributors') + session.add(bigboy) + + # searching for nothing yields no results + result = self.autocompleter.autocomplete(session, '') + self.assertEqual(len(result), 0) + + # search for 'd' yields both vendors + result = self.autocompleter.autocomplete(session, 'd') + self.assertEqual(len(result), 2) + + # search for 'big' yields just Big Boy + result = self.autocompleter.autocomplete(session, 'big') + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['value'], bigboy.uuid)