-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Stripe customer factories, use in tests #634
Changes from all commits
f5b6dc6
9ef6d8f
b9559e8
114f3e5
34ac959
9878289
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from base64 import b64encode | ||
from typing import Optional | ||
|
||
|
||
def fake_stripe_id(prefix: str, seed: str, suffix: Optional[str] = None) -> str: | ||
"""Create a fake Stripe ID for testing""" | ||
body = b64encode(seed.encode()).decode().replace("=", "") | ||
return f"{prefix}_{body}{suffix if suffix else ''}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models, stripe |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
from datetime import datetime, timezone | ||
from uuid import uuid4 | ||
|
||
import factory | ||
from factory.alchemy import SQLAlchemyModelFactory | ||
|
||
from ctms import models | ||
from ctms.database import ScopedSessionLocal | ||
from tests.data import fake_stripe_id | ||
|
||
|
||
class BaseSQLAlchemyModelFactory(SQLAlchemyModelFactory): | ||
class Meta: | ||
abstract = True | ||
sqlalchemy_session = ScopedSessionLocal | ||
|
||
|
||
class NewsletterFactory(BaseSQLAlchemyModelFactory): | ||
class Meta: | ||
model = models.Newsletter | ||
|
||
name = factory.Sequence(lambda n: f"newsletter-{n}") | ||
subscribed = True | ||
format = "T" | ||
lang = factory.Faker("language_code") | ||
source = factory.Faker("url") | ||
|
||
email = factory.SubFactory(factory="tests.factories.models.EmailFactory") | ||
|
||
|
||
class WaitlistFactory(BaseSQLAlchemyModelFactory): | ||
class Meta: | ||
model = models.Waitlist | ||
|
||
name = factory.Sequence(lambda n: f"waitlist-{n}") | ||
source = factory.Faker("url") | ||
fields = {} | ||
|
||
email = factory.SubFactory(factory="tests.factories.models.EmailFactory") | ||
|
||
|
||
class FirefoxAccountFactory(BaseSQLAlchemyModelFactory): | ||
class Meta: | ||
model = models.FirefoxAccount | ||
|
||
fxa_id = factory.LazyFunction(lambda: uuid4().hex) | ||
primary_email = factory.SelfAttribute("email.primary_email") | ||
created_date = factory.Faker("date") | ||
lang = factory.Faker("language_code") | ||
first_service = None | ||
account_deleted = False | ||
|
||
email = factory.SubFactory(factory="tests.factories.models.EmailFactory") | ||
|
||
|
||
class EmailFactory(BaseSQLAlchemyModelFactory): | ||
class Meta: | ||
model = models.Email | ||
|
||
email_id = factory.Faker("uuid4") | ||
primary_email = factory.Faker("email") | ||
basket_token = factory.Faker("uuid4") | ||
first_name = factory.Faker("first_name") | ||
last_name = factory.Faker("last_name") | ||
mailing_country = factory.Faker("country_code") | ||
email_format = "T" | ||
email_lang = factory.Faker("language_code") | ||
double_opt_in = False | ||
has_opted_out_of_email = False | ||
|
||
@factory.post_generation | ||
def newsletters(self, create, extracted, **kwargs): | ||
if not create: | ||
return | ||
if extracted: | ||
for _ in range(extracted): | ||
NewsletterFactory(email=self, **kwargs) | ||
|
||
@factory.post_generation | ||
def fxa(self, create, extracted, **kwargs): | ||
if not create: | ||
return | ||
if extracted: | ||
FirefoxAccountFactory(email=self, **kwargs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing return? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope -- since this is the
Unless you're saying that we should avoid the implicit return of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get it, |
||
|
||
|
||
class StripeCustomerFactory(BaseSQLAlchemyModelFactory): | ||
class Meta: | ||
model = models.StripeCustomer | ||
|
||
stripe_id = factory.LazyFunction(lambda: fake_stripe_id("cus", "customer")) | ||
fxa_id = factory.SelfAttribute("fxa.fxa_id") | ||
default_source_id = factory.LazyFunction( | ||
lambda: fake_stripe_id("card", "default_payment") | ||
) | ||
invoice_settings_default_payment_method_id = factory.LazyFunction( | ||
lambda: fake_stripe_id("pm", "default_payment") | ||
) | ||
stripe_created = factory.LazyFunction(lambda: datetime.now(timezone.utc)) | ||
deleted = False | ||
|
||
fxa = factory.SubFactory(factory=FirefoxAccountFactory) | ||
|
||
|
||
__all__ = ( | ||
"EmailFactory", | ||
"FirefoxAccountFactory", | ||
"NewsletterFactory", | ||
"StripeCustomerFactory", | ||
"WaitlistFactory", | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
from uuid import uuid4 | ||
|
||
import factory | ||
|
||
from tests.data import fake_stripe_id | ||
|
||
|
||
class StripeCustomerDataFactory(factory.DictFactory): | ||
class Params: | ||
fxa_id = factory.LazyFunction(lambda: uuid4().hex) | ||
|
||
id = factory.LazyFunction(lambda: fake_stripe_id("cus", "customer")) | ||
object = "customer" | ||
address = None | ||
balance = 0 | ||
created = factory.Faker("unix_time") | ||
currency = "usd" | ||
default_source = None | ||
delinquent = False | ||
description = factory.LazyAttribute(lambda o: o.fxa_id) | ||
discount = None | ||
email = factory.Faker("email") | ||
invoice_prefix = factory.Faker("bothify", text="###???###") | ||
invoice_settings = { | ||
"custom_fields": None, | ||
"default_payment_method": fake_stripe_id("pm", "payment_method"), | ||
"footer": None, | ||
} | ||
livemode = False | ||
metadata = factory.Dict({"userid": factory.SelfAttribute("..description")}) | ||
name = factory.Faker("name") | ||
next_invoice_sequence = factory.Faker("pyint") | ||
phone = None | ||
preferred_locales = [] | ||
shipping = None | ||
tax_exempt = "none" | ||
|
||
|
||
__all__ = ("StripeCustomerDataFactory",) |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
Shall we add a comment that this simulates the DB relationship?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what you mean by "simulates"? By using this factory, we'll create an
Email
andFirefoxAccount
object, and they'll be related throughfxa_instance.email
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by my own comment...
I didn't know about
SelfAttribute
and looked up its docs to understand how it was leveraged. I first understood that we were linking the two fields using this lazy attribute, as if they were linked by foreign keys in the DB.But actually, I see that
primary_email
in theFirefoxAccount
model is not linked toemail.primary_email
at all, they can be different AFAIU. So scratch that