diff --git a/opentech/apply/funds/tests/factories/models.py b/opentech/apply/funds/tests/factories/models.py index 183fb45fd8441fb79d90f0092cf7ebd476edb4f3..dfc84042f4add1de88a625ce10ae366dd6bee3dc 100644 --- a/opentech/apply/funds/tests/factories/models.py +++ b/opentech/apply/funds/tests/factories/models.py @@ -18,6 +18,7 @@ from opentech.apply.funds.models import ( RoundForm, ) from opentech.apply.users.tests.factories import StaffFactory, UserFactory +from opentech.apply.stream_forms.testing.factories import FormDataFactory from . import blocks @@ -101,9 +102,15 @@ class RoundFactory(wagtail_factories.PageFactory): class Meta: model = Round + class Params: + now = factory.Trait( + start_date=factory.LazyFunction(datetime.date.today), + end_date=factory.LazyFunction(lambda: datetime.date.today() + datetime.timedelta(days=7)), + ) + title = factory.Sequence('Round {}'.format) - start_date = factory.LazyFunction(datetime.date.today) - end_date = factory.LazyFunction(lambda: datetime.date.today() + datetime.timedelta(days=7)) + start_date = factory.Sequence(lambda n: datetime.date.today() + datetime.timedelta(days=7 * n)) + end_date = factory.Sequence(lambda n: datetime.date.today() + datetime.timedelta(days=7 * (n + 1))) lead = factory.SubFactory(StaffFactory) @factory.post_generation @@ -159,58 +166,8 @@ class LabFormFactory(AbstractRelatedFormFactory): lab = factory.SubFactory(LabFactory, parent=None) -class AnswerFactory(factory.Factory): - def _create(self, *args, sub_factory=None, **kwargs): - return sub_factory.make_answer(kwargs) - - -class Metaclass(factory.base.FactoryMetaClass): - def __new__(mcs, class_name, bases, attrs): - # Add the form field definitions to allow nested calls - wrapped_factories = { - k: factory.SubFactory(AnswerFactory, sub_factory=v) - for k, v in blocks.CustomFormFieldsFactory.factories.items() - } - attrs.update(wrapped_factories) - return super().__new__(mcs, class_name, bases, attrs) - - -class FormDataFactory(factory.Factory, metaclass=Metaclass): - def _create(self, *args, form_fields={}, clean=False, **kwargs): - if form_fields and isinstance(form_fields, str): - form_fields = json.loads(form_fields) - form_definition = { - field['type']: field['id'] - for field in form_fields - } - else: - form_definition = { - f.block_type: f.id - for f in form_fields or ApplicationSubmission.form_fields.field.to_python(form_fields) - } - - form_data = {} - for name, answer in kwargs.items(): - form_data[form_definition[name]] = answer - - if clean: - application = ApplicationSubmissionFactory(round=Round.objects.first()) - application.form_fields = form_fields - application.form_data = form_data - application.save() - form_data = application.form_data.copy() - application.delete() - return application.form_data - - return form_data - - -class ApplicationRevisionFactory(factory.DjangoModelFactory): - class Meta: - model = ApplicationRevision - - submission = factory.SubFactory('opentech.apply.funds.tests.factories.ApplicationSubmissionFactory') - form_data = factory.SubFactory(FormDataFactory, form_fields=factory.SelfAttribute('..submission.form_fields'), clean=True) +class ApplicationFormDataFactory(FormDataFactory): + field_factory = blocks.CustomFormFieldsFactory class ApplicationSubmissionFactory(factory.DjangoModelFactory): @@ -225,7 +182,10 @@ class ApplicationSubmissionFactory(factory.DjangoModelFactory): ) form_fields = blocks.CustomFormFieldsFactory - form_data = factory.SubFactory(FormDataFactory, form_fields=factory.SelfAttribute('..form_fields')) + form_data = factory.SubFactory( + ApplicationFormDataFactory, + form_fields=factory.SelfAttribute('..form_fields'), + ) page = factory.SubFactory(FundTypeFactory) workflow_name = factory.LazyAttribute(lambda o: list(FundType.WORKFLOW_CHOICES.keys())[o.workflow_stages - 1]) round = factory.SubFactory( @@ -242,3 +202,16 @@ class ApplicationSubmissionFactory(factory.DjangoModelFactory): def _generate(cls, strat, params): params.update(**build_form(params)) return super()._generate(strat, params) + + +class ApplicationRevisionFactory(factory.DjangoModelFactory): + class Meta: + model = ApplicationRevision + + submission = factory.SubFactory('opentech.apply.funds.tests.factories.ApplicationSubmissionFactory') + form_data = factory.SubFactory( + ApplicationFormDataFactory, + form_fields=factory.SelfAttribute('..submission.form_fields'), + for_factory=ApplicationSubmissionFactory, + clean=True, + ) diff --git a/opentech/apply/funds/tests/test_models.py b/opentech/apply/funds/tests/test_models.py index fe29618c062c1a9ba66001fe81429619ed2c587f..10d7609ca26723bbce696eecd77ccfbec84a1132 100644 --- a/opentech/apply/funds/tests/test_models.py +++ b/opentech/apply/funds/tests/test_models.py @@ -40,11 +40,11 @@ class TestFundModel(TestCase): self.assertIsNone(self.fund.open_round) def test_open_ended_round(self): - open_round = RoundFactory(end_date=None, parent=self.fund) + open_round = RoundFactory(start_date=date.today(), end_date=None, parent=self.fund) self.assertEqual(self.fund.open_round, open_round) def test_normal_round(self): - open_round = RoundFactory(parent=self.fund) + open_round = RoundFactory(parent=self.fund, now=True) self.assertEqual(self.fund.open_round, open_round) def test_closed_round(self): @@ -59,7 +59,7 @@ class TestFundModel(TestCase): self.assertIsNone(self.fund.open_round) def test_multiple_open_rounds(self): - open_round = RoundFactory(parent=self.fund) + open_round = RoundFactory(parent=self.fund, now=True) next_round_start = open_round.end_date + timedelta(days=1) RoundFactory(start_date=next_round_start, end_date=None, parent=self.fund) self.assertEqual(self.fund.open_round, open_round) @@ -149,10 +149,12 @@ class TestRoundModelWorkflowAndForms(TestCase): def setUp(self): self.fund = FundTypeFactory(parent=None) - self.round = RoundFactory.build() - self.round.parent_page = self.fund - self.round.lead = RoundFactory.lead.get_factory()(**RoundFactory.lead.defaults) + # Must create lead, adding child complains about "built" user with no id + lead = RoundFactory.lead.get_factory()(**RoundFactory.lead.defaults) + self.round = RoundFactory.build(lead=lead, parent=None) + # Assign parent_page like the init does + self.round.parent_page = self.fund self.fund.add_child(instance=self.round) def test_workflow_is_copied_to_new_rounds(self): @@ -190,7 +192,7 @@ class TestFormSubmission(TestCase): self.site.root_page = fund self.site.save() - self.round_page = RoundFactory(parent=fund) + self.round_page = RoundFactory(parent=fund, now=True) self.lab_page = LabFactory(lead=self.round_page.lead) def submit_form(self, page=None, email=None, name=None, user=AnonymousUser()): @@ -322,7 +324,7 @@ class TestApplicationSubmission(TestCase): submission_b = self.make_submission(round=submission_a.round) submissions = [submission_a, submission_b] self.assertEqual( - list(ApplicationSubmission.objects.order_by('email')), + list(ApplicationSubmission.objects.order_by('id')), submissions, ) @@ -331,7 +333,7 @@ class TestApplicationSubmission(TestCase): submission_b = self.make_submission(round=submission_a.round) submissions = [submission_b, submission_a] self.assertEqual( - list(ApplicationSubmission.objects.order_by('-email')), + list(ApplicationSubmission.objects.order_by('-id')), submissions, ) diff --git a/opentech/apply/review/tests/factories/models.py b/opentech/apply/review/tests/factories/models.py index 486769c3f1f8421e4d02ec8bd8e87b73419b528d..fd2374a332e1791a4386f1e32416d091da4369b9 100644 --- a/opentech/apply/review/tests/factories/models.py +++ b/opentech/apply/review/tests/factories/models.py @@ -1,15 +1,15 @@ -import json from collections import defaultdict import factory -from opentech.apply.funds.models import AbstractRelatedReviewForm, FundReviewForm, ApplicationSubmission +from opentech.apply.funds.models import AbstractRelatedReviewForm, FundReviewForm from opentech.apply.funds.tests.factories import ApplicationSubmissionFactory, FundTypeFactory from opentech.apply.review.options import YES, NO, MAYBE from opentech.apply.users.tests.factories import StaffFactory from opentech.apply.review.models import Review, ReviewForm -from opentech.apply.review.views import get_form_for_stage +from opentech.apply.review.views import get_fields_for_stage +from opentech.apply.stream_forms.testing.factories import AddFormFieldsMetaclass from . import blocks @@ -36,31 +36,17 @@ def build_form(data, prefix=''): return form_fields -class AnswerFactory(factory.Factory): - def _create(self, *args, sub_factory=None, **kwargs): - return sub_factory.make_answer(kwargs) +class ReviewFormDataFactory(factory.DictFactory, metaclass=AddFormFieldsMetaclass): + field_factory = blocks.ReviewFormFieldsFactory - -class Metaclass(factory.base.FactoryMetaClass): - def __new__(mcs, class_name, bases, attrs): - # Add the form field definitions to allow nested calls - wrapped_factories = { - k: factory.SubFactory(AnswerFactory, sub_factory=v) - for k, v in blocks.ReviewFormFieldsFactory.factories.items() - } - attrs.update(wrapped_factories) - return super().__new__(mcs, class_name, bases, attrs) - - -class ReviewFormDataFactory(factory.DictFactory, metaclass=Metaclass): @classmethod def _build(cls, model_class, *args, **kwargs): submission = kwargs.pop('submission') - form = get_form_for_stage(submission) - form_fields = {} - for field_name, field in form.get_form_fields().items(): - form_fields[field_name] = 0 + form_fields = { + field.id: 0 + for field in get_fields_for_stage(submission) + } form_fields.update(**kwargs) return super()._build(model_class, *args, **form_fields) diff --git a/opentech/apply/stream_forms/testing/factories.py b/opentech/apply/stream_forms/testing/factories.py index 856325dbb7a015959d51e5360cbb55dd6ef7b88f..50d5f7d774c8c767f71d738e923213cb11f1beed 100644 --- a/opentech/apply/stream_forms/testing/factories.py +++ b/opentech/apply/stream_forms/testing/factories.py @@ -14,6 +14,54 @@ __all__ = ['CharBlockFactory', 'FormFieldBlockFactory', 'CharFieldBlockFactory', 'MultiFileFieldBlockFactory'] +class AnswerFactory(factory.Factory): + def _create(self, *args, sub_factory=None, **kwargs): + return sub_factory.make_answer(kwargs) + + +class AddFormFieldsMetaclass(factory.base.FactoryMetaClass): + def __new__(mcs, class_name, bases, attrs): + # Add the form field definitions to allow nested calls + field_factory = attrs.pop('field_factory', None) + if field_factory: + wrapped_factories = { + k: factory.SubFactory(AnswerFactory, sub_factory=v) + for k, v in field_factory.factories.items() + } + attrs.update(wrapped_factories) + return super().__new__(mcs, class_name, bases, attrs) + + +class FormDataFactory(factory.Factory, metaclass=AddFormFieldsMetaclass): + def _create(self, *args, form_fields={}, for_factory=None, clean=False, **kwargs): + if form_fields and isinstance(form_fields, str): + form_fields = json.loads(form_fields) + form_definition = { + field['type']: field['id'] + for field in form_fields + } + else: + form_definition = { + f.block_type: f.id + for f in form_fields or for_factory.Meta.model.form_fields.field.to_python(form_fields) + } + + form_data = {} + for name, answer in kwargs.items(): + form_data[form_definition[name]] = answer + + if clean: + clean_object = for_factory() + clean_object.form_fields = form_fields + clean_object.form_data = form_data + clean_object.save() + form_data = clean_object.form_data.copy() + clean_object.delete() + return form_data + + return form_data + + class CharBlockFactory(wagtail_factories.blocks.BlockFactory): class Meta: model = CharBlock