feat: add basic support for merging 2 records, w/ preview
including basic logic for merging Person or User records
This commit is contained in:
parent
8bfbf0e570
commit
ee3a789682
10 changed files with 1554 additions and 73 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from sqlalchemy import orm
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ import colander
|
|||
|
||||
from wuttaweb.grids import Grid
|
||||
from wuttaweb.views import users as mod
|
||||
from wuttaweb.testing import WebTestCase, FunctionalTestCase
|
||||
from wuttaweb.testing import WebTestCase, VersionWebTestCase, FunctionalTestCase
|
||||
|
||||
|
||||
class TestUserView(WebTestCase):
|
||||
|
|
@ -496,6 +496,220 @@ class TestUserView(WebTestCase):
|
|||
result = view.delete_api_token()
|
||||
self.assertEqual(result, {"error": "API token not found"})
|
||||
|
||||
def test_merge_get_simple_fields(self):
|
||||
view = self.make_view()
|
||||
|
||||
# password field should not be included
|
||||
fields = view.merge_get_simple_fields()
|
||||
self.assertNotIn("password", fields)
|
||||
self.assertIn("username", fields)
|
||||
self.assertIn("active", fields)
|
||||
|
||||
def test_merge_get_additive_fields(self):
|
||||
view = self.make_view()
|
||||
|
||||
# nb. this is not a "versioned" test case, so transaction_count
|
||||
# field will not be included
|
||||
fields = view.merge_get_additive_fields()
|
||||
self.assertNotIn("transaction_count", fields)
|
||||
self.assertIn("roles", fields)
|
||||
|
||||
def test_merge_get_data(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
user = model.User(username="fred")
|
||||
user.roles.append(admin)
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
# nb. this is not a "versioned" test case, so transaction_count
|
||||
# field will not be included
|
||||
data = view.merge_get_data(user)
|
||||
self.assertEqual(data["username"], "fred")
|
||||
self.assertEqual(data["roles"], [admin.name])
|
||||
self.assertNotIn("transaction_count", data)
|
||||
|
||||
def test_merge_why_not(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
user1 = model.User(username="freddie")
|
||||
self.session.add(user1)
|
||||
user2 = model.User(username="fred")
|
||||
self.session.add(user2)
|
||||
self.session.commit()
|
||||
|
||||
# normally no reason not to merge
|
||||
self.assertIsNone(view.merge_why_not(user1, user2))
|
||||
|
||||
# can merge even if current user is involved (being kept)
|
||||
with patch.object(self.request, "user", new=user2):
|
||||
self.assertIsNone(view.merge_why_not(user1, user2))
|
||||
|
||||
# but cannot merge if it means removing current user
|
||||
with patch.object(self.request, "user", new=user1):
|
||||
reason = view.merge_why_not(user1, user2)
|
||||
self.assertEqual(reason, "Cannot remove user who is currently logged in!")
|
||||
|
||||
def test_merge_execute(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
user1 = model.User(username="freddie")
|
||||
user1.roles.append(admin)
|
||||
self.session.add(user1)
|
||||
user2 = model.User(username="fred")
|
||||
self.session.add(user2)
|
||||
|
||||
upgrade = model.Upgrade(
|
||||
description="test",
|
||||
created_by=user1,
|
||||
executed_by=user1,
|
||||
status=enum.UpgradeStatus.SUCCESS,
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
view.merge_execute(user1, user2)
|
||||
self.session.commit()
|
||||
|
||||
self.assertEqual(self.session.query(model.User).count(), 1)
|
||||
self.assertNotIn(user1, self.session)
|
||||
self.assertIn(user2, self.session)
|
||||
|
||||
self.assertIn(admin, user2.roles)
|
||||
|
||||
self.assertIs(upgrade.created_by, user2)
|
||||
self.assertIs(upgrade.executed_by, user2)
|
||||
|
||||
|
||||
class TestVersionedUserView(VersionWebTestCase):
|
||||
|
||||
def make_view(self):
|
||||
return mod.UserView(self.request)
|
||||
|
||||
def test_merge_get_additive_fields(self):
|
||||
view = self.make_view()
|
||||
|
||||
# nb. contrast this to the "non-versioned" test case above
|
||||
fields = view.merge_get_additive_fields()
|
||||
self.assertIn("transaction_count", fields)
|
||||
self.assertIn("roles", fields)
|
||||
|
||||
def test_merge_get_data(self):
|
||||
import sqlalchemy_continuum as continuum
|
||||
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
txncls = continuum.transaction_class(model.User)
|
||||
|
||||
# nb. must reset the User model reference, due to nature of
|
||||
# test setup/teardown
|
||||
with patch.multiple(
|
||||
mod.UserView,
|
||||
model_class=model.User,
|
||||
Session=MagicMock(return_value=self.session),
|
||||
):
|
||||
view = self.make_view()
|
||||
|
||||
# make admin user
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
user = model.User(username="fred")
|
||||
user.roles.append(admin)
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
self.assertEqual(self.session.query(txncls).count(), 1)
|
||||
|
||||
# nb. contrast this to the "non-versioned" test case above
|
||||
data = view.merge_get_data(user)
|
||||
self.assertEqual(data["username"], "fred")
|
||||
self.assertEqual(data["roles"], [admin.name])
|
||||
self.assertEqual(data["transaction_count"], 0)
|
||||
|
||||
# admin user then creates 2 records w/ 1 txn
|
||||
# nb. must trick wuttaweb continuum plugin to assign author
|
||||
with patch.object(self.request, "user", new=user):
|
||||
person1 = model.Person(full_name="Barney Rubble")
|
||||
self.session.add(person1)
|
||||
person2 = model.Person(full_name="Betty Rubble")
|
||||
self.session.add(person2)
|
||||
self.session.commit()
|
||||
|
||||
self.assertEqual(self.session.query(txncls).count(), 2)
|
||||
txn1, txn2 = self.session.query(txncls).order_by(txncls.id).all()
|
||||
self.assertIsNone(txn1.user)
|
||||
self.assertIs(txn2.user, user)
|
||||
|
||||
# nb. contrast this to the "non-versioned" test case above
|
||||
data = view.merge_get_data(user)
|
||||
self.assertEqual(data["username"], "fred")
|
||||
self.assertEqual(data["roles"], [admin.name])
|
||||
self.assertEqual(data["transaction_count"], 1)
|
||||
|
||||
def test_merge_execute(self):
|
||||
import sqlalchemy_continuum as continuum
|
||||
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
txncls = continuum.transaction_class(model.User)
|
||||
|
||||
# nb. must reset the User model reference, due to nature of
|
||||
# test setup/teardown
|
||||
with patch.multiple(
|
||||
mod.UserView,
|
||||
model_class=model.User,
|
||||
Session=MagicMock(return_value=self.session),
|
||||
):
|
||||
view = self.make_view()
|
||||
|
||||
# make pair of users
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
user1 = model.User(username="freddie")
|
||||
user1.roles.append(admin)
|
||||
self.session.add(user1)
|
||||
user2 = model.User(username="fred")
|
||||
self.session.add(user2)
|
||||
self.session.commit()
|
||||
self.assertEqual(self.session.query(model.User).count(), 2)
|
||||
self.assertEqual(self.session.query(txncls).count(), 1)
|
||||
|
||||
# admin user then creates 2 records w/ 1 txn
|
||||
# nb. must trick wuttaweb continuum plugin to assign author
|
||||
with patch.object(self.request, "user", new=user1):
|
||||
person1 = model.Person(full_name="Barney Rubble")
|
||||
self.session.add(person1)
|
||||
person2 = model.Person(full_name="Betty Rubble")
|
||||
self.session.add(person2)
|
||||
self.session.commit()
|
||||
|
||||
self.assertEqual(self.session.query(txncls).count(), 2)
|
||||
txn1, txn2 = self.session.query(txncls).order_by(txncls.id).all()
|
||||
self.assertIsNone(txn1.user)
|
||||
self.assertIs(txn2.user, user1)
|
||||
self.assertEqual(len(user2.roles), 0)
|
||||
|
||||
# merge user1 => user2 (as user2, for 3rd txn)
|
||||
with patch.object(self.request, "user", new=user2):
|
||||
view.merge_execute(user1, user2)
|
||||
self.session.commit()
|
||||
self.assertEqual(self.session.query(txncls).count(), 3)
|
||||
txn1, txn2, txn3 = self.session.query(txncls).order_by(txncls.id).all()
|
||||
self.assertIs(txn3.user, user2)
|
||||
self.assertEqual(self.session.query(model.User).count(), 1)
|
||||
user = self.session.query(model.User).one()
|
||||
self.assertIs(user, user2)
|
||||
|
||||
# user2 is now admin, and author of txn2
|
||||
self.assertIn(admin, user2.roles)
|
||||
self.assertIs(txn2.user, user2)
|
||||
|
||||
|
||||
# TODO: this test seems to work fine on its own, but not in conjunction
|
||||
# with the next class below. will have to sort this out before adding
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue