MASSIVE UPDATE:
bounty board feature buyers to see bounty boards seller profile page (like have theme chooser) Have the game and set name be filters. Add cards to vault manually update card inventory add to have the autocomplete for the card - store analytics, clicks, views, link to store (url/QR code) bulk item inventory creation -- Make the banner feature flag driven so I can have a beta site setup like the primary site don't use primary key values in urls - update to use uuid4 values site analytics. tianji is being sent item potent on the mtg and lorcana populate scripts Card item images for specific listings check that when you buy a card it is in the vault Buys should be able to search on store inventories More pie charts for the seller! post bounty board is slow to load seller reviews/ratings - show a historgram - need a way for someone to rate Report a seller feature for buyer to report Make sure the stlying is consistent based on the theme choosen smart minimum order quantity and shipping amounts (defined by the store itself) put virtual packs behind a feature flag like bounty board proxy service feature flag Terms of Service new description for TCGKof store SSN, ITIN, and EIN optomize for SEO
This commit is contained in:
240
store/tests.py
240
store/tests.py
@@ -1,3 +1,239 @@
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from .models import Seller, Game, Set, Card, CardListing, Order
|
||||
from decimal import Decimal
|
||||
|
||||
# Create your tests here.
|
||||
User = get_user_model()
|
||||
|
||||
class CardListingTests(TestCase):
|
||||
def setUp(self):
|
||||
# Create User and Seller
|
||||
self.user = User.objects.create_user(username='seller', password='password')
|
||||
self.seller = Seller.objects.create(
|
||||
user=self.user,
|
||||
store_name='Test Store',
|
||||
slug='test-store'
|
||||
)
|
||||
|
||||
# Create Game, Set, Card
|
||||
self.game = Game.objects.create(name='Test Game', slug='test-game')
|
||||
self.set = Set.objects.create(game=self.game, name='Test Set')
|
||||
self.card = Card.objects.create(set=self.set, name='Test Card')
|
||||
|
||||
# Create Listing
|
||||
self.listing = CardListing.objects.create(
|
||||
card=self.card,
|
||||
seller=self.seller,
|
||||
price=10.00,
|
||||
quantity=1,
|
||||
condition='NM'
|
||||
)
|
||||
|
||||
self.client = Client()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_edit_card_listing_image_upload(self):
|
||||
url = reverse('store:edit_card_listing', args=[self.listing.uuid])
|
||||
|
||||
# Create a small image file
|
||||
image_content = b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b'
|
||||
image = SimpleUploadedFile("test_image.gif", image_content, content_type="image/gif")
|
||||
|
||||
data = {
|
||||
'condition': 'LP',
|
||||
'price': '15.00',
|
||||
'quantity': 2,
|
||||
'status': 'listed',
|
||||
'image': image
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, format='multipart')
|
||||
|
||||
# Check redirect
|
||||
self.assertRedirects(response, reverse('store:manage_listings'))
|
||||
|
||||
# Reload listing
|
||||
self.listing.refresh_from_db()
|
||||
|
||||
# Check updates
|
||||
self.assertEqual(self.listing.condition, 'LP')
|
||||
self.assertEqual(self.listing.price, 15.00)
|
||||
self.assertEqual(self.listing.quantity, 2)
|
||||
|
||||
# Check image
|
||||
self.assertTrue(self.listing.image)
|
||||
self.assertTrue(self.listing.image.name.endswith('test_image.gif'))
|
||||
|
||||
class SellerDashboardTests(TestCase):
|
||||
def setUp(self):
|
||||
# Create User and Seller
|
||||
self.user = User.objects.create_user(username='dashboard_seller', password='password')
|
||||
self.seller = Seller.objects.create(
|
||||
user=self.user,
|
||||
store_name='Dashboard Store',
|
||||
slug='dashboard-store'
|
||||
)
|
||||
self.buyer_user = User.objects.create_user(username='buyer', password='password')
|
||||
from users.models import Buyer
|
||||
self.buyer = Buyer.objects.create(user=self.buyer_user)
|
||||
|
||||
# Create Game, Set, Card
|
||||
self.game = Game.objects.create(name='Dashboard Game', slug='dashboard-game')
|
||||
self.set = Set.objects.create(game=self.game, name='Dashboard Set')
|
||||
self.card = Card.objects.create(set=self.set, name='Dashboard Card')
|
||||
|
||||
# Create Listing
|
||||
self.listing = CardListing.objects.create(
|
||||
card=self.card,
|
||||
seller=self.seller,
|
||||
price=10.00,
|
||||
quantity=10,
|
||||
condition='NM'
|
||||
)
|
||||
|
||||
# Create Order & OrderItem
|
||||
from .models import Order, OrderItem
|
||||
self.order = Order.objects.create(
|
||||
buyer=self.buyer,
|
||||
status='paid',
|
||||
total_price=20.00
|
||||
)
|
||||
OrderItem.objects.create(
|
||||
order=self.order,
|
||||
listing=self.listing,
|
||||
price_at_purchase=10.00,
|
||||
quantity=2
|
||||
)
|
||||
|
||||
self.client = Client()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_dashboard_context_data(self):
|
||||
url = reverse('store:seller_dashboard')
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check for new context keys
|
||||
self.assertIn('condition_labels', response.context)
|
||||
self.assertIn('condition_data', response.context)
|
||||
self.assertIn('set_labels', response.context)
|
||||
self.assertIn('set_data', response.context)
|
||||
self.assertIn('game_labels', response.context)
|
||||
self.assertIn('game_data', response.context)
|
||||
self.assertIn('all_games', response.context)
|
||||
|
||||
# Check data correctness (we sold 2 NM items)
|
||||
import json
|
||||
cond_data = json.loads(response.context['condition_data'])
|
||||
cond_labels = json.loads(response.context['condition_labels'])
|
||||
|
||||
self.assertIn('Near Mint', cond_labels)
|
||||
idx = cond_labels.index('Near Mint')
|
||||
self.assertEqual(cond_data[idx], 2)
|
||||
|
||||
def test_dashboard_game_filter(self):
|
||||
from .models import OrderItem
|
||||
url = reverse('store:seller_dashboard')
|
||||
|
||||
# Create another game/sale
|
||||
game2 = Game.objects.create(name='Other Game', slug='other-game')
|
||||
set2 = Set.objects.create(game=game2, name='Other Set')
|
||||
card2 = Card.objects.create(set=set2, name='Other Card')
|
||||
listing2 = CardListing.objects.create(card=card2, seller=self.seller, price=5, quantity=5, condition='LP')
|
||||
|
||||
OrderItem.objects.create(
|
||||
order=self.order,
|
||||
listing=listing2,
|
||||
price_at_purchase=5.00,
|
||||
quantity=1
|
||||
)
|
||||
|
||||
# 1. No Filter - Should see both
|
||||
response = self.client.get(url)
|
||||
import json
|
||||
game_labels = json.loads(response.context['game_labels'])
|
||||
self.assertIn('Dashboard Game', game_labels)
|
||||
self.assertIn('Other Game', game_labels)
|
||||
|
||||
# 2. Filter by Dashboard Game
|
||||
response = self.client.get(url, {'game': 'Dashboard Game'})
|
||||
game_labels = json.loads(response.context['game_labels'])
|
||||
self.assertIn('Dashboard Game', game_labels)
|
||||
self.assertNotIn('Other Game', game_labels)
|
||||
|
||||
# Check condition data also filtered
|
||||
cond_labels = json.loads(response.context['condition_labels'])
|
||||
# Dashboard Game items were NM. Other Game items were LP.
|
||||
self.assertIn('Near Mint', cond_labels)
|
||||
self.assertNotIn('Lightly Played', cond_labels)
|
||||
|
||||
class AdminRevenueTests(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.staff_user = User.objects.create_user(username='staff', password='password', is_staff=True)
|
||||
self.seller_user = User.objects.create_user(username='seller2', password='password')
|
||||
|
||||
self.seller = Seller.objects.create(
|
||||
user=self.seller_user,
|
||||
store_name='Revenue Store',
|
||||
slug='revenue-store',
|
||||
tax_id='123-45-6789',
|
||||
payout_details='Bank Acct 123'
|
||||
)
|
||||
|
||||
# Create Orders
|
||||
from users.models import Buyer
|
||||
buyer_user = User.objects.create_user(username='buyer2', password='password')
|
||||
buyer = Buyer.objects.create(user=buyer_user)
|
||||
|
||||
# Order 1: $100 -> Fee: 5 + 0.70 = 5.70
|
||||
order1 = Order.objects.create(buyer=buyer, status='paid', total_price=Decimal('100.00'), seller=self.seller)
|
||||
|
||||
# Order 2: $1000 -> Fee: 50 + 0.70 = 50.70 -> Capped at 25.00
|
||||
order2 = Order.objects.create(buyer=buyer, status='shipped', total_price=Decimal('1000.00'), seller=self.seller)
|
||||
|
||||
# Order 3: Pending (should be ignored)
|
||||
order3 = Order.objects.create(buyer=buyer, status='pending', total_price=Decimal('50.00'), seller=self.seller)
|
||||
|
||||
def test_encryption(self):
|
||||
# Refresh from db
|
||||
seller = Seller.objects.get(pk=self.seller.pk)
|
||||
|
||||
# Verify decrypted values match
|
||||
self.assertEqual(seller.tax_id, '123-45-6789')
|
||||
self.assertEqual(seller.payout_details, 'Bank Acct 123')
|
||||
|
||||
# Verify db values are encrypted (not plaintext and are bytes)
|
||||
self.assertIsInstance(seller.tax_id_encrypted, bytes)
|
||||
self.assertNotEqual(seller.tax_id_encrypted, b'123-45-6789')
|
||||
# Ensure it's not just the string encoded
|
||||
self.assertNotEqual(seller.tax_id_encrypted, '123-45-6789'.encode('utf-8'))
|
||||
|
||||
def test_fee_calculation(self):
|
||||
from .utils import calculate_platform_fee
|
||||
# 5% + 0.70
|
||||
self.assertEqual(calculate_platform_fee(Decimal('10.00')), Decimal('1.20')) # 0.50 + 0.70
|
||||
self.assertEqual(calculate_platform_fee(Decimal('100.00')), Decimal('5.70')) # 5.00 + 0.70
|
||||
|
||||
# Cap at 25
|
||||
# Threshold: (25 - 0.70) / 0.05 = 486.00
|
||||
self.assertEqual(calculate_platform_fee(Decimal('486.00')), Decimal('25.00'))
|
||||
self.assertEqual(calculate_platform_fee(Decimal('1000.00')), Decimal('25.00'))
|
||||
|
||||
def test_dashboard_view(self):
|
||||
self.client.force_login(self.staff_user)
|
||||
response = self.client.get(reverse('store:admin_revenue_dashboard'))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check context
|
||||
total_rev = response.context['total_platform_revenue']
|
||||
# Order 1 (5.70) + Order 2 (25.00) = 30.70
|
||||
self.assertEqual(total_rev, Decimal('30.70'))
|
||||
|
||||
seller_data = response.context['seller_data']
|
||||
self.assertEqual(len(seller_data), 1)
|
||||
self.assertEqual(seller_data[0]['total_revenue'], Decimal('1100.00'))
|
||||
self.assertEqual(seller_data[0]['platform_fees'], Decimal('30.70'))
|
||||
|
||||
Reference in New Issue
Block a user