Compare commits

..

2 commits

Author SHA1 Message Date
796b687719 implement simple backend search for items and tickets
Some checks failed
/ test (push) Failing after 51s
/ test (pull_request) Failing after 50s
2024-11-23 01:52:34 +01:00
d5eadbe4b1 add timeline information to the /items endpoint
All checks were successful
/ test (push) Successful in 52s
/ deploy (push) Successful in 4m37s
2024-11-23 01:22:24 +01:00
8 changed files with 205 additions and 174 deletions

View file

@ -20,9 +20,12 @@ jobs:
- name: Run django tests - name: Run django tests
working-directory: core working-directory: core
run: python3 manage.py test run: python3 manage.py test
- name: Run django coverage
working-directory: core
run: coverage manage.py test
deploy: deploy:
needs: [test] needs: [ test ]
runs-on: docker runs-on: docker
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View file

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from inventory.models import Item, Container, ItemPlacement, Comment, Event from inventory.models import Item, Container, Event
class ItemAdmin(admin.ModelAdmin): class ItemAdmin(admin.ModelAdmin):
@ -22,17 +22,3 @@ class EventAdmin(admin.ModelAdmin):
admin.site.register(Event, EventAdmin) admin.site.register(Event, EventAdmin)
class ItemPlacementAdmin(admin.ModelAdmin):
pass
admin.site.register(ItemPlacement, ItemPlacementAdmin)
class CommentAdmin(admin.ModelAdmin):
pass
admin.site.register(Comment, CommentAdmin)

View file

@ -0,0 +1,36 @@
# Generated by Django 4.2.7 on 2024-11-23 00:19
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_alter_event_table'),
]
operations = [
migrations.RemoveField(
model_name='item',
name='container',
),
migrations.CreateModel(
name='ItemPlacement',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('container', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_history', to='inventory.container')),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='container_history', to='inventory.item')),
],
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('comment', models.TextField()),
('timestamp', models.DateTimeField(auto_now_add=True)),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='inventory.item')),
],
),
]

View file

@ -1,52 +0,0 @@
# Generated by Django 4.2.7 on 2024-11-23 15:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_alter_event_table'),
]
def set_initial_container(apps, schema_editor):
Item = apps.get_model('inventory', 'Item')
for item in Item.objects.all():
item.container_history.get_or_create(container=item.container_old)
item.save()
operations = [
migrations.RenameField(
model_name='item',
old_name='container',
new_name='container_old',
),
migrations.CreateModel(
name='ItemPlacement',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('container',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_history',
to='inventory.container')),
('item',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='container_history',
to='inventory.item')),
],
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('comment', models.TextField()),
('timestamp', models.DateTimeField(auto_now_add=True)),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments',
to='inventory.item')),
],
),
migrations.RunPython(set_initial_container),
migrations.RemoveField(
model_name='item',
name='container_old',
),
]

View file

@ -92,7 +92,7 @@ class Comment(models.Model):
timestamp = models.DateTimeField(auto_now_add=True) timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self): def __str__(self):
return str(self.item) + ' comment #' + str(self.id) return str(self.issue_thread) + ' comment #' + str(self.id)
class Event(models.Model): class Event(models.Model):

View file

@ -106,14 +106,6 @@ class ItemSerializer(BasicItemSerializer):
'timestamp': relation.timestamp, 'timestamp': relation.timestamp,
'issue_thread': BasicIssueSerializer(relation.issue_thread).data, 'issue_thread': BasicIssueSerializer(relation.issue_thread).data,
}) })
for placement in (obj.container_history.all()):
timeline.append({
'type': 'placement',
'id': placement.id,
'timestamp': placement.timestamp,
'cid': placement.container.id,
'box': placement.container.name
})
return sorted(timeline, key=lambda x: x['timestamp']) return sorted(timeline, key=lambda x: x['timestamp'])

View file

@ -7,20 +7,21 @@ from knox.models import AuthToken
from authentication.models import ExtendedUser from authentication.models import ExtendedUser
from files.models import File from files.models import File
from inventory.models import Event, Container, Item, Comment, ItemPlacement from inventory.models import Event, Container, Item, Comment
from base64 import b64encode from base64 import b64encode
from tickets.models import IssueThread, ItemRelation from tickets.models import IssueThread, ItemRelation
from base64 import b64encode
class ItemTestCase(TestCase): class ItemTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.event = Event.objects.create(slug='EVENT', name='Event') self.event = Event.objects.create(slug='EVENT', name='Event')
self.box1 = Container.objects.create(name='BOX1') self.box = Container.objects.create(name='BOX')
self.box2 = Container.objects.create(name='BOX2')
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test') self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
self.user.user_permissions.add(*Permission.objects.all()) self.user.user_permissions.add(*Permission.objects.all())
self.token = AuthToken.objects.create(user=self.user) self.token = AuthToken.objects.create(user=self.user)
@ -37,7 +38,7 @@ class ItemTestCase(TestCase):
def test_members_and_timeline(self): def test_members_and_timeline(self):
now = datetime.now() now = datetime.now()
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
comment = Comment.objects.create( comment = Comment.objects.create(
item=item, item=item,
comment="test", comment="test",
@ -45,12 +46,7 @@ class ItemTestCase(TestCase):
) )
match = ItemRelation.objects.create( match = ItemRelation.objects.create(
issue_thread=self.issue, issue_thread=self.issue,
item=item, item = item,
timestamp=now + timedelta(seconds=4),
)
placement = ItemPlacement.objects.create(
container=self.box2,
item=item,
timestamp=now + timedelta(seconds=5), timestamp=now + timedelta(seconds=5),
) )
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
@ -58,34 +54,25 @@ class ItemTestCase(TestCase):
self.assertEqual(len(response.json()), 1) self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]['id'], item.id) self.assertEqual(response.json()[0]['id'], item.id)
self.assertEqual(response.json()[0]['description'], '1') self.assertEqual(response.json()[0]['description'], '1')
self.assertEqual(response.json()[0]['box'], 'BOX2') self.assertEqual(response.json()[0]['box'], 'BOX')
self.assertEqual(response.json()[0]['cid'], self.box2.id) self.assertEqual(response.json()[0]['cid'], self.box.id)
self.assertEqual(response.json()[0]['file'], None) self.assertEqual(response.json()[0]['file'], None)
self.assertEqual(response.json()[0]['returned'], False) self.assertEqual(response.json()[0]['returned'], False)
self.assertEqual(response.json()[0]['event'], self.event.slug) self.assertEqual(response.json()[0]['event'], self.event.slug)
self.assertEqual(len(response.json()[0]['timeline']), 4) self.assertEqual(len(response.json()[0]['timeline']), 2)
self.assertEqual(response.json()[0]['timeline'][0]['type'], 'placement') self.assertEqual(response.json()[0]['timeline'][0]['type'], 'comment')
self.assertEqual(response.json()[0]['timeline'][1]['type'], 'comment') self.assertEqual(response.json()[0]['timeline'][1]['type'], 'issue_relation')
self.assertEqual(response.json()[0]['timeline'][2]['type'], 'issue_relation') self.assertEqual(response.json()[0]['timeline'][0]['id'], comment.id)
self.assertEqual(response.json()[0]['timeline'][3]['type'], 'placement') self.assertEqual(response.json()[0]['timeline'][1]['id'], match.id)
self.assertEqual(response.json()[0]['timeline'][1]['id'], comment.id) self.assertEqual(response.json()[0]['timeline'][0]['comment'], 'test')
self.assertEqual(response.json()[0]['timeline'][2]['id'], match.id) self.assertEqual(response.json()[0]['timeline'][0]['timestamp'],
self.assertEqual(response.json()[0]['timeline'][3]['id'], placement.id)
self.assertEqual(response.json()[0]['timeline'][0]['box'], 'BOX1')
self.assertEqual(response.json()[0]['timeline'][0]['cid'], self.box1.id)
self.assertEqual(response.json()[0]['timeline'][1]['comment'], 'test')
self.assertEqual(response.json()[0]['timeline'][1]['timestamp'],
comment.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ')) comment.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
self.assertEqual(response.json()[0]['timeline'][2]['status'], 'possible') self.assertEqual(response.json()[0]['timeline'][1]['status'], 'possible')
self.assertEqual(response.json()[0]['timeline'][2]['timestamp'], self.assertEqual(response.json()[0]['timeline'][1]['timestamp'],
match.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ')) match.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
self.assertEqual(response.json()[0]['timeline'][2]['issue_thread']['name'], "test issue") self.assertEqual(response.json()[0]['timeline'][1]['issue_thread']['name'], "test issue")
self.assertEqual(response.json()[0]['timeline'][2]['issue_thread']['event'], "EVENT") self.assertEqual(response.json()[0]['timeline'][1]['issue_thread']['event'], "EVENT")
self.assertEqual(response.json()[0]['timeline'][2]['issue_thread']['state'], "pending_new") self.assertEqual(response.json()[0]['timeline'][1]['issue_thread']['state'], "pending_new")
self.assertEqual(response.json()[0]['timeline'][3]['box'], 'BOX2')
self.assertEqual(response.json()[0]['timeline'][3]['cid'], self.box2.id)
self.assertEqual(response.json()[0]['timeline'][3]['timestamp'],
placement.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
self.assertEqual(len(response.json()[0]['related_issues']), 1) self.assertEqual(len(response.json()[0]['related_issues']), 1)
self.assertEqual(response.json()[0]['related_issues'][0]['name'], "test issue") self.assertEqual(response.json()[0]['related_issues'][0]['name'], "test issue")
self.assertEqual(response.json()[0]['related_issues'][0]['event'], "EVENT") self.assertEqual(response.json()[0]['related_issues'][0]['event'], "EVENT")
@ -93,15 +80,15 @@ class ItemTestCase(TestCase):
def test_members_with_file(self): def test_members_with_file(self):
import base64 import base64
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
file = File.objects.create(item=item, data="data:text/plain;base64," + base64.b64encode(b"foo").decode('utf-8')) file = File.objects.create(item=item, data="data:text/plain;base64," + base64.b64encode(b"foo").decode('utf-8'))
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 1) self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]['id'], item.id) self.assertEqual(response.json()[0]['id'], item.id)
self.assertEqual(response.json()[0]['description'], '1') self.assertEqual(response.json()[0]['description'], '1')
self.assertEqual(response.json()[0]['box'], 'BOX1') self.assertEqual(response.json()[0]['box'], 'BOX')
self.assertEqual(response.json()[0]['cid'], self.box1.id) self.assertEqual(response.json()[0]['cid'], self.box.id)
self.assertEqual(response.json()[0]['file'], file.hash) self.assertEqual(response.json()[0]['file'], file.hash)
self.assertEqual(response.json()[0]['returned'], False) self.assertEqual(response.json()[0]['returned'], False)
self.assertEqual(response.json()[0]['event'], self.event.slug) self.assertEqual(response.json()[0]['event'], self.event.slug)
@ -109,38 +96,36 @@ class ItemTestCase(TestCase):
def test_members_with_two_file(self): def test_members_with_two_file(self):
import base64 import base64
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
file1 = File.objects.create(item=item, file1 = File.objects.create(item=item, data="data:text/plain;base64," + base64.b64encode(b"foo").decode('utf-8'))
data="data:text/plain;base64," + base64.b64encode(b"foo").decode('utf-8')) file2 = File.objects.create(item=item, data="data:text/plain;base64," + base64.b64encode(b"bar").decode('utf-8'))
file2 = File.objects.create(item=item,
data="data:text/plain;base64," + base64.b64encode(b"bar").decode('utf-8'))
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 1) self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]['id'], item.id) self.assertEqual(response.json()[0]['id'], item.id)
self.assertEqual(response.json()[0]['description'], '1') self.assertEqual(response.json()[0]['description'], '1')
self.assertEqual(response.json()[0]['box'], 'BOX1') self.assertEqual(response.json()[0]['box'], 'BOX')
self.assertEqual(response.json()[0]['cid'], self.box1.id) self.assertEqual(response.json()[0]['cid'], self.box.id)
self.assertEqual(response.json()[0]['file'], file2.hash) self.assertEqual(response.json()[0]['file'], file2.hash)
self.assertEqual(response.json()[0]['returned'], False) self.assertEqual(response.json()[0]['returned'], False)
self.assertEqual(response.json()[0]['event'], self.event.slug) self.assertEqual(response.json()[0]['event'], self.event.slug)
self.assertEqual(len(response.json()[0]['related_issues']), 0) self.assertEqual(len(response.json()[0]['related_issues']), 0)
def test_multi_members(self): def test_multi_members(self):
Item.objects.create(container=self.box1, event=self.event, description='1') Item.objects.create(container=self.box, event=self.event, description='1')
Item.objects.create(container=self.box1, event=self.event, description='2') Item.objects.create(container=self.box, event=self.event, description='2')
Item.objects.create(container=self.box1, event=self.event, description='3') Item.objects.create(container=self.box, event=self.event, description='3')
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 3) self.assertEqual(len(response.json()), 3)
def test_create_item(self): def test_create_item(self):
response = self.client.post(f'/api/2/{self.event.slug}/item/', {'cid': self.box1.id, 'description': '1'}) response = self.client.post(f'/api/2/{self.event.slug}/item/', {'cid': self.box.id, 'description': '1'})
self.assertEqual(response.status_code, 201) self.assertEqual(response.status_code, 201)
self.assertEqual(response.json()['id'], 1) self.assertEqual(response.json()['id'], 1)
self.assertEqual(response.json()['description'], '1') self.assertEqual(response.json()['description'], '1')
self.assertEqual(response.json()['box'], 'BOX1') self.assertEqual(response.json()['box'], 'BOX')
self.assertEqual(response.json()['cid'], self.box1.id) self.assertEqual(response.json()['cid'], self.box.id)
self.assertEqual(response.json()['file'], None) self.assertEqual(response.json()['file'], None)
self.assertEqual(response.json()['returned'], False) self.assertEqual(response.json()['returned'], False)
self.assertEqual(response.json()['event'], self.event.slug) self.assertEqual(response.json()['event'], self.event.slug)
@ -148,43 +133,43 @@ class ItemTestCase(TestCase):
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
self.assertEqual(Item.objects.all()[0].id, 1) self.assertEqual(Item.objects.all()[0].id, 1)
self.assertEqual(Item.objects.all()[0].description, '1') self.assertEqual(Item.objects.all()[0].description, '1')
self.assertEqual(Item.objects.all()[0].container.id, self.box1.id) self.assertEqual(Item.objects.all()[0].container.id, self.box.id)
def test_create_item_without_container(self): def test_create_item_without_container(self):
response = self.client.post(f'/api/2/{self.event.slug}/item/', {'description': '1'}) response = self.client.post(f'/api/2/{self.event.slug}/item/', {'description': '1'})
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
def test_create_item_without_description(self): def test_create_item_without_description(self):
response = self.client.post(f'/api/2/{self.event.slug}/item/', {'cid': self.box1.id}) response = self.client.post(f'/api/2/{self.event.slug}/item/', {'cid': self.box.id})
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
def test_create_item_with_file(self): def test_create_item_with_file(self):
import base64 import base64
response = self.client.post(f'/api/2/{self.event.slug}/item/', response = self.client.post(f'/api/2/{self.event.slug}/item/',
{'cid': self.box1.id, 'description': '1', {'cid': self.box.id, 'description': '1',
'dataImage': "data:text/plain;base64," + base64.b64encode(b"foo").decode( 'dataImage': "data:text/plain;base64," + base64.b64encode(b"foo").decode(
'utf-8')}, content_type='application/json') 'utf-8')}, content_type='application/json')
self.assertEqual(response.status_code, 201) self.assertEqual(response.status_code, 201)
self.assertEqual(response.json()['id'], 1) self.assertEqual(response.json()['id'], 1)
self.assertEqual(response.json()['description'], '1') self.assertEqual(response.json()['description'], '1')
self.assertEqual(response.json()['box'], 'BOX1') self.assertEqual(response.json()['box'], 'BOX')
self.assertEqual(response.json()['id'], self.box1.id) self.assertEqual(response.json()['id'], self.box.id)
self.assertEqual(len(response.json()['file']), 64) self.assertEqual(len(response.json()['file']), 64)
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
self.assertEqual(Item.objects.all()[0].id, 1) self.assertEqual(Item.objects.all()[0].id, 1)
self.assertEqual(Item.objects.all()[0].description, '1') self.assertEqual(Item.objects.all()[0].description, '1')
self.assertEqual(Item.objects.all()[0].container.id, self.box1.id) self.assertEqual(Item.objects.all()[0].container.id, self.box.id)
self.assertEqual(len(File.objects.all()), 1) self.assertEqual(len(File.objects.all()), 1)
def test_update_item(self): def test_update_item(self):
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
response = self.client.patch(f'/api/2/{self.event.slug}/item/{item.id}/', {'description': '2'}, response = self.client.patch(f'/api/2/{self.event.slug}/item/{item.id}/', {'description': '2'},
content_type='application/json') content_type='application/json')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()['id'], item.id) self.assertEqual(response.json()['id'], item.id)
self.assertEqual(response.json()['description'], '2') self.assertEqual(response.json()['description'], '2')
self.assertEqual(response.json()['box'], 'BOX1') self.assertEqual(response.json()['box'], 'BOX')
self.assertEqual(response.json()['cid'], self.box1.id) self.assertEqual(response.json()['cid'], self.box.id)
self.assertEqual(response.json()['file'], None) self.assertEqual(response.json()['file'], None)
self.assertEqual(response.json()['returned'], False) self.assertEqual(response.json()['returned'], False)
self.assertEqual(response.json()['event'], self.event.slug) self.assertEqual(response.json()['event'], self.event.slug)
@ -192,62 +177,60 @@ class ItemTestCase(TestCase):
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
self.assertEqual(Item.objects.all()[0].id, 1) self.assertEqual(Item.objects.all()[0].id, 1)
self.assertEqual(Item.objects.all()[0].description, '2') self.assertEqual(Item.objects.all()[0].description, '2')
self.assertEqual(Item.objects.all()[0].container.id, self.box1.id) self.assertEqual(Item.objects.all()[0].container.id, self.box.id)
def test_update_item_with_file(self): def test_update_item_with_file(self):
import base64 import base64
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
response = self.client.patch(f'/api/2/{self.event.slug}/item/{item.id}/', response = self.client.patch(f'/api/2/{self.event.slug}/item/{item.id}/',
{'description': '2', {'description': '2',
'dataImage': "data:text/plain;base64," + base64.b64encode(b"foo").decode( 'dataImage': "data:text/plain;base64," + base64.b64encode(b"foo").decode('utf-8')},
'utf-8')}, content_type='application/json')
content_type='application/json')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()['id'], 1) self.assertEqual(response.json()['id'], 1)
self.assertEqual(response.json()['description'], '2') self.assertEqual(response.json()['description'], '2')
self.assertEqual(response.json()['box'], 'BOX1') self.assertEqual(response.json()['box'], 'BOX')
self.assertEqual(response.json()['id'], self.box1.id) self.assertEqual(response.json()['id'], self.box.id)
self.assertEqual(len(response.json()['file']), 64) self.assertEqual(len(response.json()['file']), 64)
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
self.assertEqual(Item.objects.all()[0].id, 1) self.assertEqual(Item.objects.all()[0].id, 1)
self.assertEqual(Item.objects.all()[0].description, '2') self.assertEqual(Item.objects.all()[0].description, '2')
self.assertEqual(Item.objects.all()[0].container.id, self.box1.id) self.assertEqual(Item.objects.all()[0].container.id, self.box.id)
self.assertEqual(len(File.objects.all()), 1) self.assertEqual(len(File.objects.all()), 1)
def test_delete_item(self): def test_delete_item(self):
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
Item.objects.create(container=self.box1, event=self.event, description='2') Item.objects.create(container=self.box, event=self.event, description='2')
self.assertEqual(len(Item.objects.all()), 2) self.assertEqual(len(Item.objects.all()), 2)
response = self.client.delete(f'/api/2/{self.event.slug}/item/{item.id}/') response = self.client.delete(f'/api/2/{self.event.slug}/item/{item.id}/')
self.assertEqual(response.status_code, 204) self.assertEqual(response.status_code, 204)
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
def test_delete_item2(self): def test_delete_item2(self):
Item.objects.create(container=self.box1, event=self.event, description='1') Item.objects.create(container=self.box, event=self.event, description='1')
item2 = Item.objects.create(container=self.box1, event=self.event, description='2') item2 = Item.objects.create(container=self.box, event=self.event, description='2')
self.assertEqual(len(Item.objects.all()), 2) self.assertEqual(len(Item.objects.all()), 2)
response = self.client.delete(f'/api/2/{self.event.slug}/item/{item2.id}/') response = self.client.delete(f'/api/2/{self.event.slug}/item/{item2.id}/')
self.assertEqual(response.status_code, 204) self.assertEqual(response.status_code, 204)
self.assertEqual(len(Item.objects.all()), 1) self.assertEqual(len(Item.objects.all()), 1)
item3 = Item.objects.create(container=self.box1, event=self.event, description='3') item3 = Item.objects.create(container=self.box, event=self.event, description='3')
self.assertEqual(item3.id, 3) self.assertEqual(item3.id, 3)
self.assertEqual(len(Item.objects.all()), 2) self.assertEqual(len(Item.objects.all()), 2)
def test_item_count(self): def test_item_count(self):
Item.objects.create(container=self.box1, event=self.event, description='1') Item.objects.create(container=self.box, event=self.event, description='1')
Item.objects.create(container=self.box1, event=self.event, description='2') Item.objects.create(container=self.box, event=self.event, description='2')
response = self.client.get('/api/2/boxes/') response = self.client.get('/api/2/boxes/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 2) self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]['itemCount'], 2) self.assertEqual(response.json()[0]['itemCount'], 2)
self.assertEqual(response.json()[1]['itemCount'], 0)
def test_item_nonexistent(self): def test_item_nonexistent(self):
response = self.client.get(f'/api/2/NOEVENT/item/') response = self.client.get(f'/api/2/NOEVENT/item/')
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
def test_item_return(self): def test_item_return(self):
item = Item.objects.create(container=self.box1, event=self.event, description='1') item = Item.objects.create(container=self.box, event=self.event, description='1')
self.assertEqual(item.returned_at, None) self.assertEqual(item.returned_at, None)
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -262,8 +245,8 @@ class ItemTestCase(TestCase):
self.assertEqual(len(response.json()), 0) self.assertEqual(len(response.json()), 0)
def test_item_show_not_returned(self): def test_item_show_not_returned(self):
item1 = Item.objects.create(container=self.box1, event=self.event, description='1') item1 = Item.objects.create(container=self.box, event=self.event, description='1')
item2 = Item.objects.create(container=self.box1, event=self.event, description='2') item2 = Item.objects.create(container=self.box, event=self.event, description='2')
response = self.client.get(f'/api/2/{self.event.slug}/item/') response = self.client.get(f'/api/2/{self.event.slug}/item/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 2) self.assertEqual(len(response.json()), 2)
@ -280,15 +263,15 @@ class ItemSearchTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.event = Event.objects.create(slug='EVENT', name='Event') self.event = Event.objects.create(slug='EVENT', name='Event')
self.box1 = Container.objects.create(name='BOX1') self.box = Container.objects.create(name='BOX')
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test') self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
self.user.user_permissions.add(*Permission.objects.all()) self.user.user_permissions.add(*Permission.objects.all())
self.token = AuthToken.objects.create(user=self.user) self.token = AuthToken.objects.create(user=self.user)
self.client = Client(headers={'Authorization': 'Token ' + self.token[1]}) self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
self.item1 = Item.objects.create(container=self.box1, event=self.event, description='abc def') self.item1 = Item.objects.create(container=self.box, event=self.event, description='abc def')
self.item2 = Item.objects.create(container=self.box1, event=self.event, description='def ghi') self.item2 = Item.objects.create(container=self.box, event=self.event, description='def ghi')
self.item3 = Item.objects.create(container=self.box1, event=self.event, description='jkl mno pqr') self.item3 = Item.objects.create(container=self.box, event=self.event, description='jkl mno pqr')
self.item4 = Item.objects.create(container=self.box1, event=self.event, description='stu vwx') self.item4 = Item.objects.create(container=self.box, event=self.event, description='stu vwx')
def test_search(self): def test_search(self):
search_query = b64encode(b'abc').decode('utf-8') search_query = b64encode(b'abc').decode('utf-8')
@ -297,8 +280,8 @@ class ItemSearchTestCase(TestCase):
self.assertEqual(1, len(response.json())) self.assertEqual(1, len(response.json()))
self.assertEqual(self.item1.id, response.json()[0]['id']) self.assertEqual(self.item1.id, response.json()[0]['id'])
self.assertEqual('abc def', response.json()[0]['description']) self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX1', response.json()[0]['box']) self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box1.id, response.json()[0]['cid']) self.assertEqual(self.box.id, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score']) self.assertEqual(1, response.json()[0]['search_score'])
def test_search2(self): def test_search2(self):
@ -308,13 +291,13 @@ class ItemSearchTestCase(TestCase):
self.assertEqual(2, len(response.json())) self.assertEqual(2, len(response.json()))
self.assertEqual(self.item1.id, response.json()[0]['id']) self.assertEqual(self.item1.id, response.json()[0]['id'])
self.assertEqual('abc def', response.json()[0]['description']) self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX1', response.json()[0]['box']) self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box1.id, response.json()[0]['cid']) self.assertEqual(self.box.id, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score']) self.assertEqual(1, response.json()[0]['search_score'])
self.assertEqual(self.item2.id, response.json()[1]['id']) self.assertEqual(self.item2.id, response.json()[1]['id'])
self.assertEqual('def ghi', response.json()[1]['description']) self.assertEqual('def ghi', response.json()[1]['description'])
self.assertEqual('BOX1', response.json()[1]['box']) self.assertEqual('BOX', response.json()[1]['box'])
self.assertEqual(self.box1.id, response.json()[1]['cid']) self.assertEqual(self.box.id, response.json()[1]['cid'])
self.assertEqual(1, response.json()[0]['search_score']) self.assertEqual(1, response.json()[0]['search_score'])
def test_search3(self): def test_search3(self):
@ -324,8 +307,8 @@ class ItemSearchTestCase(TestCase):
self.assertEqual(1, len(response.json())) self.assertEqual(1, len(response.json()))
self.assertEqual(self.item3.id, response.json()[0]['id']) self.assertEqual(self.item3.id, response.json()[0]['id'])
self.assertEqual('jkl mno pqr', response.json()[0]['description']) self.assertEqual('jkl mno pqr', response.json()[0]['description'])
self.assertEqual('BOX1', response.json()[0]['box']) self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box1.id, response.json()[0]['cid']) self.assertEqual(self.box.id, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score']) self.assertEqual(1, response.json()[0]['search_score'])
def test_search4(self): def test_search4(self):
@ -335,11 +318,83 @@ class ItemSearchTestCase(TestCase):
self.assertEqual(2, len(response.json())) self.assertEqual(2, len(response.json()))
self.assertEqual(self.item1.id, response.json()[0]['id']) self.assertEqual(self.item1.id, response.json()[0]['id'])
self.assertEqual('abc def', response.json()[0]['description']) self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX1', response.json()[0]['box']) self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box1.id, response.json()[0]['cid']) self.assertEqual(self.box.id, response.json()[0]['cid'])
self.assertEqual(2, response.json()[0]['search_score']) self.assertEqual(2, response.json()[0]['search_score'])
self.assertEqual(self.item2.id, response.json()[1]['id']) self.assertEqual(self.item2.id, response.json()[1]['id'])
self.assertEqual('def ghi', response.json()[1]['description']) self.assertEqual('def ghi', response.json()[1]['description'])
self.assertEqual('BOX1', response.json()[1]['box']) self.assertEqual('BOX', response.json()[1]['box'])
self.assertEqual(self.box1.id, response.json()[1]['cid']) self.assertEqual(self.box.id, response.json()[1]['cid'])
self.assertEqual(1, response.json()[1]['search_score']) self.assertEqual(1, response.json()[1]['search_score'])
class ItemSearchTestCase(TestCase):
def setUp(self):
super().setUp()
self.event = Event.objects.create(slug='EVENT', name='Event')
self.box = Container.objects.create(name='BOX')
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
self.user.user_permissions.add(*Permission.objects.all())
self.token = AuthToken.objects.create(user=self.user)
self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
self.item1 = Item.objects.create(container=self.box, event=self.event, description='abc def')
self.item2 = Item.objects.create(container=self.box, event=self.event, description='def ghi')
self.item3 = Item.objects.create(container=self.box, event=self.event, description='jkl mno pqr')
self.item4 = Item.objects.create(container=self.box, event=self.event, description='stu vwx')
def test_search(self):
search_query = b64encode(b'abc').decode('utf-8')
response = self.client.get(f'/api/2/{self.event.slug}/items/{search_query}/')
self.assertEqual(200, response.status_code)
self.assertEqual(1, len(response.json()))
self.assertEqual(self.item1.uid, response.json()[0]['uid'])
self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box.cid, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score'])
def test_search2(self):
search_query = b64encode(b'def').decode('utf-8')
response = self.client.get(f'/api/2/{self.event.slug}/items/{search_query}/')
self.assertEqual(200, response.status_code)
self.assertEqual(2, len(response.json()))
self.assertEqual(self.item1.uid, response.json()[0]['uid'])
self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box.cid, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score'])
self.assertEqual(self.item2.uid, response.json()[1]['uid'])
self.assertEqual('def ghi', response.json()[1]['description'])
self.assertEqual('BOX', response.json()[1]['box'])
self.assertEqual(self.box.cid, response.json()[1]['cid'])
self.assertEqual(1, response.json()[0]['search_score'])
def test_search3(self):
search_query = b64encode(b'jkl').decode('utf-8')
response = self.client.get(f'/api/2/{self.event.slug}/items/{search_query}/')
self.assertEqual(200, response.status_code)
self.assertEqual(1, len(response.json()))
self.assertEqual(self.item3.uid, response.json()[0]['uid'])
self.assertEqual('jkl mno pqr', response.json()[0]['description'])
self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box.cid, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score'])
def test_search4(self):
search_query = b64encode(b'abc def').decode('utf-8')
response = self.client.get(f'/api/2/{self.event.slug}/items/{search_query}/')
self.assertEqual(200, response.status_code)
self.assertEqual(2, len(response.json()))
self.assertEqual(self.item1.uid, response.json()[0]['uid'])
self.assertEqual('abc def', response.json()[0]['description'])
self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box.cid, response.json()[0]['cid'])
self.assertEqual(2, response.json()[0]['search_score'])
self.assertEqual(self.item2.uid, response.json()[1]['uid'])
self.assertEqual('def ghi', response.json()[1]['description'])
self.assertEqual('BOX', response.json()[1]['box'])
self.assertEqual(self.box.cid, response.json()[1]['cid'])
self.assertEqual(1, response.json()[1]['search_score'])

View file

@ -130,6 +130,17 @@ class IssueSerializer(BasicIssueSerializer):
class SearchResultSerializer(serializers.Serializer):
search_score = serializers.IntegerField()
item = IssueSerializer()
def to_representation(self, instance):
return {**IssueSerializer(instance['item']).data, 'search_score': instance['search_score']}
class Meta:
model = IssueThread
class SearchResultSerializer(serializers.Serializer): class SearchResultSerializer(serializers.Serializer):
search_score = serializers.IntegerField() search_score = serializers.IntegerField()
item = IssueSerializer() item = IssueSerializer()