Best Python code snippet using slash
fixture.py
Source:fixture.py  
1import datetime2from django.contrib.auth.models import Group3from django.contrib.contenttypes.models import ContentType4from django.utils import timezone5from pinax.eventlog.models import Log6import address.models as ad7from api.v1.tests.factories import GoalMetricFactory, TransactionFactory, PositionLotFactory, \8    InvestmentCycleObservationFactory9from client.models import Client, ClientAccount, IBAccount, RiskProfileAnswer, \10    RiskProfileGroup, RiskProfileQuestion11from main.constants import ACCOUNT_TYPE_PERSONAL12from main.event import Event13from main.models import Advisor, AssetClass, DailyPrice, Execution, \14    ExecutionDistribution, ExternalAsset, Firm, Goal, \15    GoalMetricGroup, GoalSetting, GoalType, HistoricalBalance, MarketIndex, \16    PortfolioSet, Region, Ticker, User, ExternalInstrument, \17    Transaction, MarketOrderRequest18from main.risk_profiler import MINIMUM_RISK19from retiresmartz.models import RetirementPlan20class Fixture1:21    @classmethod22    def portfolioset1(cls):23        params = {24            'name': 'portfolioset1',25            'risk_free_rate': 0.02,26        }27        return PortfolioSet.objects.get_or_create(id=1, defaults=params)[0]28    @classmethod29    def portfolioset2(cls):30        params = {31            'name': 'portfolioset2',32            'risk_free_rate': 0.02,33        }34        return PortfolioSet.objects.get_or_create(id=2, defaults=params)[0]35    @classmethod36    def firm1(cls):37        params = {38            'name': 'example_inc',39            'token': 'example_inc',40            'default_portfolio_set': Fixture1.portfolioset1(),41        }42        return Firm.objects.get_or_create(slug='example_inc', defaults=params)[0]43    @classmethod44    def user_group_advisors(cls):45        return Group.objects.get_or_create(name=User.GROUP_ADVISOR)[0]46    @classmethod47    def user_group_clients(cls):48        return Group.objects.get_or_create(name=User.GROUP_CLIENT)[0]49    @classmethod50    def advisor1_user(cls):51        params = {52            'first_name': "test",53            'last_name': "advisor",54        }55        i, c = User.objects.get_or_create(email="advisor@example.com", defaults=params)56        if c:57            i.groups.add(Fixture1.user_group_advisors())58        return i59    @classmethod60    def address1(cls):61        region = ad.Region.objects.get_or_create(name='Here', country='AU')[0]62        return ad.Address.objects.get_or_create(address='My House', post_code='1000', region=region)[0]63    @classmethod64    def address2(cls):65        region = ad.Region.objects.get_or_create(name='Here', country='AU')[0]66        return ad.Address.objects.get_or_create(address='My House 2', post_code='1000', region=region)[0]67    @classmethod68    def advisor1(cls):69        params = {70            'firm': Fixture1.firm1(),71            'betasmartz_agreement': True,72            'default_portfolio_set': Fixture1.portfolioset1(),73            'residential_address': Fixture1.address1(),74        }75        return Advisor.objects.get_or_create(user=Fixture1.advisor1_user(), defaults=params)[0]76    @classmethod77    def client1_user(cls):78        params = {79            'first_name': "test",80            'last_name': "client",81        }82        i, c = User.objects.get_or_create(email="client@example.com", defaults=params)83        if c:84            i.groups.add(Fixture1.user_group_clients())85        return i86    @classmethod87    def client2_user(cls):88        params = {89            'first_name': "test",90            'last_name': "client_2",91        }92        return User.objects.get_or_create(email="client2@example.com", defaults=params)[0]93    @classmethod94    def client1(cls):95        params = {96            'advisor': Fixture1.advisor1(),97            'user': Fixture1.client1_user(),98            'date_of_birth': datetime.date(1970, 1, 1),99            'residential_address': Fixture1.address2(),100            'risk_profile_group': Fixture1.risk_profile_group1(),101        }102        return Client.objects.get_or_create(id=1, defaults=params)[0]103    @classmethod104    def client2(cls):105        params = {106            'advisor': Fixture1.advisor1(),107            'user': Fixture1.client2_user(),108            'date_of_birth': datetime.date(1980, 1, 1),109            'residential_address': Fixture1.address2(),110            'risk_profile_group': Fixture1.risk_profile_group2(),111        }112        return Client.objects.get_or_create(id=2, defaults=params)[0]113    @classmethod114    def client1_retirementplan1(cls):115        return RetirementPlan.objects.get_or_create(id=1, defaults={116            'name': 'Plan1',117            'client': Fixture1.client1(),118            'desired_income': 60000,119            'income': 80000,120            'volunteer_days': 1,121            'paid_days': 2,122            'same_home': True,123            'reverse_mortgage': True,124            'expected_return_confidence': 0.5,125            'retirement_age': 65,126            'btc': 50000,127            'atc': 30000,128            'desired_risk': 0.6,129            'recommended_risk': 0.5,130            'max_risk': 1.0,131            'calculated_life_expectancy': 73,132            'selected_life_expectancy': 80,133        })[0]134    @classmethod135    def client2_retirementplan1(cls):136        return RetirementPlan.objects.get_or_create(id=2, defaults={137            'name': 'Plan1',138            'client': Fixture1.client2(),139            'desired_income': 60000,140            'income': 80000,141            'volunteer_days': 1,142            'paid_days': 2,143            'same_home': True,144            'reverse_mortgage': True,145            'expected_return_confidence': 0.5,146            'retirement_age': 65,147            'btc': 50000,148            'atc': 30000,149            'desired_risk': 0.6,150            'recommended_risk': 0.5,151            'max_risk': 1.0,152            'calculated_life_expectancy': 73,153            'selected_life_expectancy': 80,154                                                    })[0]155    @classmethod156    def client2_retirementplan2(cls):157        return RetirementPlan.objects.get_or_create(id=4, defaults={158            'name': 'Plan2',159            'client': Fixture1.client2(),160            'desired_income': 60000,161            'income': 80000,162            'volunteer_days': 1,163            'paid_days': 2,164            'same_home': True,165            'reverse_mortgage': True,166            'expected_return_confidence': 0.5,167            'retirement_age': 65,168            'btc': 50000,169            'atc': 30000,170            'desired_risk': 0.6,171            'recommended_risk': 0.5,172            'max_risk': 1.0,173            'calculated_life_expectancy': 73,174            'selected_life_expectancy': 80,175                                                    })[0]176    @classmethod177    def client1_partneredplan(cls):178        plan1 = Fixture1.client1_retirementplan1()179        plan2 = Fixture1.client2_retirementplan1()180        plan1.partner_plan = plan2181        plan2.partner_plan = plan1182        plan1.save()183        plan2.save()184        return plan1185    @classmethod186    def risk_profile_group1(cls):187        return RiskProfileGroup.objects.get_or_create(name='risk_profile_group1')[0]188    @classmethod189    def risk_profile_group2(cls):190        return RiskProfileGroup.objects.get_or_create(name='risk_profile_group2')[0]191    @classmethod192    def risk_profile_question1(cls):193        return RiskProfileQuestion.objects.get_or_create(group=Fixture1.risk_profile_group1(),194                                                         order=0,195                                                         text='How much do you like risk?')[0]196    @classmethod197    def risk_profile_question2(cls):198        return RiskProfileQuestion.objects.get_or_create(group=Fixture1.risk_profile_group1(),199                                                         order=1,200                                                         text='How sophisticated are you?')[0]201    @classmethod202    def risk_profile_question3(cls):203        return RiskProfileQuestion.objects.get_or_create(group=Fixture1.risk_profile_group1(),204                                                         order=2,205                                                         text='Have you used other wealth management software?')[0]206    @classmethod207    def risk_profile_answer1a(cls):208        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question1(),209                                                       order=0,210                                                       text='A lot',211                                                       b_score=9,212                                                       a_score=9,213                                                       s_score=9)[0]214    @classmethod215    def risk_profile_answer1b(cls):216        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question1(),217                                                       order=1,218                                                       text='A little',219                                                       b_score=2,220                                                       a_score=2,221                                                       s_score=2)[0]222    @classmethod223    def risk_profile_answer1c(cls):224        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question1(),225                                                       order=2,226                                                       text="I'm smart but scared",227                                                       b_score=1,228                                                       a_score=9,229                                                       s_score=9)[0]230    @classmethod231    def risk_profile_answer1d(cls):232        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question1(),233                                                       order=3,234                                                       text="I'm clueless and wild",235                                                       b_score=9,236                                                       a_score=1,237                                                       s_score=1)[0]238    @classmethod239    def risk_profile_answer2a(cls):240        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question2(),241                                                       order=0,242                                                       text='Very',243                                                       b_score=9,244                                                       a_score=9,245                                                       s_score=9)[0]246    @classmethod247    def risk_profile_answer2b(cls):248        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question2(),249                                                       order=1,250                                                       text="I'm basically a peanut",251                                                       b_score=1,252                                                       a_score=1,253                                                       s_score=1)[0]254    @classmethod255    def risk_profile_answer2c(cls):256        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question2(),257                                                       order=2,258                                                       text="I'm smart but scared",259                                                       b_score=1,260                                                       a_score=9,261                                                       s_score=9)[0]262    @classmethod263    def risk_profile_answer2d(cls):264        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question2(),265                                                       order=3,266                                                       text="I'm clueless and wild",267                                                       b_score=9,268                                                       a_score=1,269                                                       s_score=1)[0]270    @classmethod271    def risk_profile_answer3a(cls):272        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question3(),273                                                       order=0,274                                                       text='Yes',275                                                       b_score=9,276                                                       a_score=9,277                                                       s_score=9)[0]278    @classmethod279    def risk_profile_answer3b(cls):280        return RiskProfileAnswer.objects.get_or_create(question=Fixture1.risk_profile_question3(),281                                                       order=1,282                                                       text='No',283                                                       b_score=1,284                                                       a_score=1,285                                                       s_score=1)[0]286    @classmethod287    def populate_risk_profile_questions(cls):288        Fixture1.risk_profile_question1()289        Fixture1.risk_profile_answer1a()290        Fixture1.risk_profile_answer1b()291        Fixture1.risk_profile_question2()292        Fixture1.risk_profile_answer2a()293        Fixture1.risk_profile_answer2b()294        # Don't create question3 here, we use that to test validation295        # that risk is NEUTRAL when the questions have changed296    @classmethod297    def populate_risk_profile_responses(cls):298        Fixture1.personal_account1().primary_owner.risk_profile_responses.add(Fixture1.risk_profile_answer1a())299        Fixture1.personal_account1().primary_owner.risk_profile_responses.add(Fixture1.risk_profile_answer2a())300    @classmethod301    def ib_account1(cls) -> IBAccount:302        params = {303            'ib_account': 'DU299694',304            'bs_account': Fixture1.personal_account1()305        }306        return IBAccount.objects.get_or_create(id=1, defaults=params)[0]307    @classmethod308    def ib_account2(cls) -> IBAccount:309        params = {310            'ib_account': 'DU299695',311            'bs_account': Fixture1.personal_account2()312        }313        return IBAccount.objects.get_or_create(id=2, defaults=params)[0]314    @classmethod315    def personal_account1(cls) -> ClientAccount:316        params = {317            'account_type': ACCOUNT_TYPE_PERSONAL,318            'primary_owner': Fixture1.client1(),319            'default_portfolio_set': Fixture1.portfolioset1(),320            'confirmed': True,321        }322        return ClientAccount.objects.get_or_create(id=1, defaults=params)[0]323    @classmethod324    def personal_account2(cls) -> ClientAccount:325        params = {326            'account_type': ACCOUNT_TYPE_PERSONAL,327            'primary_owner': Fixture1.client2(),328            'default_portfolio_set': Fixture1.portfolioset2(),329            'confirmed': True,330        }331        return ClientAccount.objects.get_or_create(id=2, defaults=params)[0]332    @classmethod333    def metric_group1(cls):334        g, c = GoalMetricGroup.objects.get_or_create(type=GoalMetricGroup.TYPE_PRESET,335                                                     name='metricgroup1')336        # A metric group isn't valid without a risk score, and we only want to create the metric if the group was337        # newly created.338        if c:339            GoalMetricFactory.create(group=g, configured_val=MINIMUM_RISK)340        return g341    @classmethod342    def metric_group2(cls):343        g, c = GoalMetricGroup.objects.get_or_create(type=GoalMetricGroup.TYPE_PRESET,344                                                     name='metricgroup2')345        # A metric group isn't valid without a risk score, and we only want to create the metric if the group was346        # newly created.347        if c:348            GoalMetricFactory.create(group=g, configured_val=MINIMUM_RISK)349        return g350    @classmethod351    def settings1(cls):352        return GoalSetting.objects.get_or_create(target=100000,353                                                 completion=datetime.date(2000, 1, 1),354                                                 hedge_fx=False,355                                                 metric_group=Fixture1.metric_group1(),356                                                 rebalance=False)[0]357    @classmethod358    def settings2(cls):359        return GoalSetting.objects.get_or_create(target=100000,360                                                 completion=datetime.date(2000, 1, 1),361                                                 hedge_fx=False,362                                                 metric_group=Fixture1.metric_group2(),363                                                 rebalance=False)[0]364    @classmethod365    def goal_type1(cls):366        return GoalType.objects.get_or_create(name='goaltype1',367                                              default_term=5,368                                              risk_sensitivity=7.0)[0]369    @classmethod370    def goal_type2(cls):371        return GoalType.objects.get_or_create(name='goaltype2',372                                              default_term=5,373                                              risk_sensitivity=7.0)[0]374    @classmethod375    def goal1(cls):376        return Goal.objects.get_or_create(account=Fixture1.personal_account1(),377                                          name='goal1',378                                          type=Fixture1.goal_type1(),379                                          portfolio_set=Fixture1.portfolioset1(),380                                          selected_settings=Fixture1.settings1())[0]381    @classmethod382    def goal2(cls):383        return Goal.objects.get_or_create(account=Fixture1.personal_account2(),384                                          name='goal2',385                                          type=Fixture1.goal_type2(),386                                          portfolio_set=Fixture1.portfolioset2(),387                                          selected_settings=Fixture1.settings2())[0]388    @classmethod389    def settings_event1(cls):390        return Log.objects.get_or_create(user=Fixture1.client1_user(),391                                         timestamp=timezone.make_aware(datetime.datetime(2000, 1, 1)),392                                         action=Event.APPROVE_SELECTED_SETTINGS.name,393                                         extra={'reason': 'Just because'},394                                         defaults={'obj': Fixture1.goal1()})[0]395    @classmethod396    def settings_event2(cls):397        return Log.objects.get_or_create(user=Fixture1.client1_user(),398                                         timestamp=timezone.make_aware(datetime.datetime(2000, 1, 1, 1)),399                                         action=Event.UPDATE_SELECTED_SETTINGS.name,400                                         extra={'reason': 'Just because 2'},401                                         defaults={'obj': Fixture1.goal1()})[0]402    @classmethod403    def transaction_event1(cls):404        # This will populate the associated Transaction as well.405        return Log.objects.get_or_create(user=Fixture1.client1_user(),406                                         timestamp=timezone.make_aware(datetime.datetime(2001, 1, 1)),407                                         action=Event.GOAL_DEPOSIT_EXECUTED.name,408                                         extra={'reason': 'Goal Deposit',409                                                'txid': Fixture1.transaction1().id},410                                         defaults={'obj': Fixture1.goal1()})[0]411    @classmethod412    def transaction1(cls):413        i, c = Transaction.objects.get_or_create(reason=Transaction.REASON_DEPOSIT,414                                                 to_goal=Fixture1.goal1(),415                                                 amount=3000,416                                                 status=Transaction.STATUS_EXECUTED,417                                                 created=timezone.make_aware(datetime.datetime(2000, 1, 1)),418                                                 executed=timezone.make_aware(datetime.datetime(2001, 1, 1)))419        if c:420            i.created = timezone.make_aware(datetime.datetime(2000, 1, 1))421            i.save()422        return i423    @classmethod424    def transaction2(cls):425        i, c = Transaction.objects.get_or_create(reason=Transaction.REASON_ORDER,426                                                 to_goal=Fixture1.goal1(),427                                                 amount=3000,428                                                 status=Transaction.STATUS_PENDING,429                                                 created=timezone.make_aware(datetime.datetime(2000, 1, 1))430                                                 )431        if c:432            i.created = timezone.make_aware(datetime.datetime(2000, 1, 1))433            i.save()434        return i435    @classmethod436    def pending_deposit1(cls):437        i, c = Transaction.objects.get_or_create(reason=Transaction.REASON_DEPOSIT,438                                                 to_goal=Fixture1.goal1(),439                                                 amount=4000,440                                                 status=Transaction.STATUS_PENDING,441                                                 created=timezone.make_aware(datetime.datetime(2000, 1, 1, 1)))442        if c:443            i.created = timezone.make_aware(datetime.datetime(2000, 1, 1, 1))444            i.save()445        return i446    @classmethod447    def pending_withdrawal1(cls):448        i, c = Transaction.objects.get_or_create(reason=Transaction.REASON_DEPOSIT,449                                                 from_goal=Fixture1.goal1(),450                                                 amount=3500,451                                                 status=Transaction.STATUS_PENDING,452                                                 created=timezone.make_aware(datetime.datetime(2000, 1, 1, 2)))453        if c:454            i.created = timezone.make_aware(datetime.datetime(2000, 1, 1, 2))455            i.save()456        return i457    @classmethod458    def populate_balance1(cls):459        HistoricalBalance.objects.get_or_create(goal=Fixture1.goal1(),460                                                date=datetime.date(2000, 12, 31),461                                                balance=0)462        HistoricalBalance.objects.get_or_create(goal=Fixture1.goal1(),463                                                date=datetime.date(2001, 1, 1),464                                                balance=3000)465    @classmethod466    def asset_class1(cls):467        params = {468            'display_order': 0,469            'display_name': 'Test Asset Class 1',470            'investment_type_id': 2,  # STOCKS pk 2, BONDS pk 1, MIXED pk 3471        }472        # Asset class name needs to be upper case.473        return AssetClass.objects.get_or_create(name='ASSETCLASS1', defaults=params)[0]474    @classmethod475    def region1(cls):476        return Region.objects.get_or_create(name='TestRegion1')[0]477    @classmethod478    def market_index1(cls):479        params = {480            'display_name': 'Test Market Index 1',481            'url': 'nowhere.com',482            'currency': 'AUD',483            'region': Fixture1.region1(),484            'data_api': 'portfolios.api.bloomberg',485            'data_api_param': 'MI1',486        }487        return MarketIndex.objects.get_or_create(id=1, defaults=params)[0]488    @classmethod489    def market_index1_daily_prices(cls):490        prices = [100, 110, 105, 103, 107]491        start_date = datetime.date(2016, 4, 1)492        d = start_date493        fund = cls.market_index1()494        for p in prices:495            fund.daily_prices.create(date=d, price=p)496            d += datetime.timedelta(1)497    @classmethod498    def market_index2(cls):499        params = {500            'display_name': 'Test Market Index 2',501            'url': 'nowhere.com',502            'currency': 'AUD',503            'region': Fixture1.region1(),504            'data_api': 'portfolios.api.bloomberg',505            'data_api_param': 'MI2',506        }507        return MarketIndex.objects.get_or_create(id=1, defaults=params)[0]508    @classmethod509    def fund1(cls):510        params = {511            'display_name': 'Test Fund 1',512            'url': 'nowhere.com/1',513            'currency': 'AUD',514            'region': Fixture1.region1(),515            'ordering': 0,516            'asset_class': Fixture1.asset_class1(),517            'benchmark': Fixture1.market_index1(),518            'data_api': 'portfolios.api.bloomberg',519            'data_api_param': 'FUND1',520        }521        return Ticker.objects.get_or_create(symbol='TSTSYMBOL1', defaults=params)[0]522    @classmethod523    def fund2(cls):524        params = {525            'display_name': 'Test Fund 2',526            'url': 'nowhere.com/2',527            'currency': 'AUD',528            'region': Fixture1.region1(),529            'ordering': 1,530            'asset_class': Fixture1.asset_class1(),531            'benchmark': Fixture1.market_index2(),532            'data_api': 'portfolios.api.bloomberg',533            'data_api_param': 'FUND2',534        }535        return Ticker.objects.get_or_create(symbol='TSTSYMBOL2', defaults=params)[0]536    @classmethod537    def fund3(cls):538        params = {539            'display_name': 'Test Fund 2',540            'url': 'nowhere.com/2',541            'currency': 'AUD',542            'region': Fixture1.region1(),543            'ordering': 1,544            'asset_class': Fixture1.asset_class1(),545            'benchmark': Fixture1.market_index2(),546            'data_api': 'portfolios.api.bloomberg',547            'data_api_param': 'FUND3',548        }549        return Ticker.objects.get_or_create(symbol='SPY', defaults=params)[0]550    @classmethod551    def fund4(cls):552        params = {553            'display_name': 'Test Fund 2',554            'url': 'nowhere.com/2',555            'currency': 'AUD',556            'region': Fixture1.region1(),557            'ordering': 1,558            'asset_class': Fixture1.asset_class1(),559            'benchmark': Fixture1.market_index2(),560            'data_api': 'portfolios.api.bloomberg',561            'data_api_param': 'FUND4',562        }563        return Ticker.objects.get_or_create(symbol='TLT', defaults=params)[0]564    @classmethod565    def external_instrument1(cls):566        params = {567            'institution': ExternalInstrument.Institution.APEX.value,568            'instrument_id': 'SPY_APEX',569            'ticker': Fixture1.fund3()570        }571        return ExternalInstrument.objects.get_or_create(id=1,defaults=params)[0]572    @classmethod573    def external_instrument2(cls):574        params = {575            'institution': ExternalInstrument.Institution.INTERACTIVE_BROKERS.value,576            'instrument_id': 'SPY_IB',577            'ticker': Fixture1.fund3()578        }579        return ExternalInstrument.objects.get_or_create(id=2,defaults=params)[0]580    @classmethod581    def external_debt_1(cls):582        params = {583            'type': ExternalAsset.Type.PROPERTY_LOAN.value,584            # description intentionally omitted to test optionality585            'valuation': '-145000',586            'valuation_date': datetime.date(2016, 7, 5),587            'growth': '0.03',588            'acquisition_date': datetime.date(2016, 7, 3),589        }590        return ExternalAsset.objects.get_or_create(name='My Home Loan', owner=Fixture1.client1(), defaults=params)[0]591    @classmethod592    def external_asset_1(cls):593        '''594        Creates and returns an asset with an associated debt.595        :return:596        '''597        params = {598            'type': ExternalAsset.Type.FAMILY_HOME.value,599            'description': 'This is my beautiful home',600            'valuation': '345000.014',601            'valuation_date': datetime.date(2016, 7, 5),602            'growth': '0.01',603            # trasfer_plan intentionally omitted as there isn't one604            'acquisition_date': datetime.date(2016, 7, 3),605            'debt': Fixture1.external_debt_1(),606        }607        return ExternalAsset.objects.get_or_create(name='My Home', owner=Fixture1.client1(), defaults=params)[0]608    @classmethod609    def set_prices(cls, prices):610        """611        Sets the prices for the given instruments and dates.612        :param prices:613        :return:614        """615        for asset, dstr, price in prices:616            DailyPrice.objects.update_or_create(instrument_object_id=asset.id,617                                                instrument_content_type=ContentType.objects.get_for_model(asset),618                                                date=datetime.datetime.strptime(dstr, '%Y%m%d'),619                                                defaults={'price': price})620    @classmethod621    def add_orders(cls, order_details):622        """623        Adds a bunch of orders to the system624        :param order_details: Iterable of (account, order_state) tuples.625        :return: the newly created orders as a list.626        """627        res = []628        for account, state in order_details:629            res.append(MarketOrderRequest.objects.create(state=state.value, account=account))630        return res631    @classmethod632    def add_executions(cls, execution_details):633        """634        Adds a bunch of order executions to the system635        :param execution_details: Iterable of (asset, order, volume, price, amount, time) tuples.636        :return: the newly created executions as a list.637        """638        res = []639        for asset, order, volume, price, amount, time in execution_details:640            res.append(Execution.objects.create(asset=asset,641                                                volume=volume,642                                                order=order,643                                                price=price,644                                                executed=timezone.make_aware(datetime.datetime.strptime(time, '%Y%m%d')),645                                                amount=amount))646        return res647    @classmethod648    def add_execution_distributions(cls, distribution_details):649        """650        Adds a bunch of order execution distributions to the system651        :param distribution_details: Iterable of (execution, volume, goal) tuples.652        :return: the newly created distributions as a list.653        """654        res = []655        for execution, volume, goal in distribution_details:656            amount = abs(execution.amount * volume / execution.volume)657            if volume > 0:658                tx = Transaction.objects.create(reason=Transaction.REASON_EXECUTION,659                                                from_goal=goal,660                                                amount=amount,661                                                status=Transaction.STATUS_EXECUTED,662                                                executed=execution.executed)663            else:664                tx = Transaction.objects.create(reason=Transaction.REASON_EXECUTION,665                                                to_goal=goal,666                                                amount=amount,667                                                status=Transaction.STATUS_EXECUTED,668                                                executed=execution.executed)669            tx.created = execution.executed670            tx.save()671            res.append(ExecutionDistribution.objects.create(execution=execution,672                                                            transaction=tx,673                                                            volume=volume))674        return res675    @classmethod676    def populate_observations(cls, values, begin_date):677        dates = list()678        values = str(values)679        for val in values:680            dates.append(begin_date)681            InvestmentCycleObservationFactory.create(as_of=begin_date,682                                                     cycle=int(val))683            begin_date += datetime.timedelta(1)684        return dates685    @classmethod686    def create_execution_details(cls, goal, ticker, quantity, price, executed):687        mor = MarketOrderRequest.objects.create(state=MarketOrderRequest.State.COMPLETE.value, account=goal.account)688        execution = Execution.objects.create(asset=ticker,689                                             volume=quantity,690                                             order=mor,691                                             price=price,692                                             executed=executed,693                                             amount=quantity*price)694        transaction = TransactionFactory.create(reason=Transaction.REASON_EXECUTION,695                                                to_goal=None,696                                                from_goal=goal,697                                                status=Transaction.STATUS_EXECUTED,698                                                executed=executed,699                                                amount=quantity*price)700        distribution = ExecutionDistribution.objects.create(execution=execution,701                                                            transaction=transaction,702                                                            volume=quantity)...Cinematic.spec.js
Source:Cinematic.spec.js  
1/* eslint-env jasmine */2import {3  getLeftCharacterThangTypeSlug,4  getRightCharacterThangTypeSlug,5  getLeftHero,6  getRightHero,7  getClearBackgroundObject,8  getBackgroundObject,9  getBackgroundObjectDelay,10  getBackground,11  getClearText,12  getSpeaker,13  getBackgroundSlug,14  getExitCharacter,15  getTextPosition,16  getText,17  getCamera,18  getTextAnimationLength,19  getSpeakingAnimationAction,20  getSetupMusic,21  getSoundEffects,22  getWaitUserInput,23  getLanguageFilter,24  getHeroPet25} from '../../../app/schemas/models/selectors/cinematic'26/**27 * This data can be used to check that none of the selectors that match28 * the left or right character work.29 * Intentionally invalid data.30 */31const invalidThangTypesSetupData = [32  { shotSetup: {} },33  { dialogNodes: [] },34  { shotSetup: { camera: 'dual' } },35  { shotSetup: { rightThangType: {} } },36  { shotSetup: { backgroundArt: {} } },37  { shotSetup: { leftThangType: undefined } },38  { shotSetup: { leftThangType: { slug: 'abc', rand: 123 } } },39  { shotSetup: { rightThangType: undefined } },40  { shotSetup: { rightThangType: { slug: 'abc', rand: 123 } } }41]42describe('Cinematic', () => {43  describe('Selectors', () => {44    getCharacterThangTypeSlugTest(getLeftCharacterThangTypeSlug, 'getLeftCharacterThangTypeSlug', invalidThangTypesSetupData, 'leftThangType')45    getCharacterThangTypeSlugTest(getRightCharacterThangTypeSlug, 'getRightCharacterThangTypeSlug', invalidThangTypesSetupData, 'rightThangType')46    it('getLeftCharacterThangTypeSlug', () => {47      const result = getLeftCharacterThangTypeSlug(shotFixture1)48      expect(result).toBeUndefined()49      const result2 = getLeftCharacterThangTypeSlug(shotFixture2)50      expect(result2).toEqual({ slug: 'fake-slug-thangtype', enterOnStart: false, thang: { scaleX: 1.2, scaleY: 1.2, pos: { x: -30, y: -72 } } })51    })52    it('getRightCharacterThangTypeSlug', () => {53      const result = getRightCharacterThangTypeSlug(shotFixture2)54      expect(result).toBeUndefined()55      const result2 = getRightCharacterThangTypeSlug(shotFixture1)56      expect(result2).toEqual({ slug: 'fake-slug-thangtype', enterOnStart: false, thang: { scaleX: 1.2, scaleY: 1.2, pos: { x: 30, y: -72 } } })57    })58    it('getLeftHero', () => {59      const result = getLeftHero(shotFixture1)60      expect(result).toEqual({ enterOnStart: true, thang: { scaleX: 1, scaleY: 13, pos: { x: 3, y: 10 } } })61      const result2 = getLeftHero(shotFixture2)62      expect(result2).toBeUndefined()63    })64    it('getRightHero', () => {65      const result = getRightHero(shotFixture2)66      expect(result).toEqual({ enterOnStart: true, thang: { scaleX: 1, scaleY: 13, pos: { x: 3, y: 10 } } })67      const result2 = getRightHero(shotFixture1)68      expect(result2).toBeUndefined()69    })70    it('getClearBackgroundObject', () => {71      const result = getClearBackgroundObject(shotFixture1.dialogNodes[0])72      expect(result).toEqual(7331)73      const result2 = getClearBackgroundObject(shotFixture2.dialogNodes[0])74      expect(result2).toBeUndefined()75    })76    it('getBackgroundObject', () => {77      const result = getBackgroundObject(shotFixture1.dialogNodes[0])78      expect(result).toEqual({ scaleX: 1, scaleY: 1, pos: { x: 0, y: 0 }, type: { slug: 'background-obj-fixture' } })79      const result2 = getBackgroundObject(shotFixture2.dialogNodes[0])80      expect(result2).toBeUndefined()81    })82    it('getBackgroundObjectDelay', () => {83      const result = getBackgroundObjectDelay(shotFixture1.dialogNodes[0])84      expect(result).toEqual(1337)85      const result2 = getBackgroundObjectDelay(shotFixture2.dialogNodes[0])86      expect(result2).toBeUndefined()87    })88    it('getBackground', () => {89      const result = getBackground(shotFixture1)90      expect(result).toEqual({ slug: 'background-fixture-slug', thang: { scaleX: 0.3, scaleY: 0.2, pos: { x: 17, y: 18 } } })91      const result2 = getBackground(shotFixture2)92      expect(result2).toBeUndefined()93    })94    it('getClearText', () => {95      const result = getClearText(shotFixture1.dialogNodes[0])96      expect(result).toEqual(false)97      const result2 = getClearText(shotFixture2.dialogNodes[0])98      expect(result2).toEqual(true)99    })100    it('getSpeaker', () => {101      const result = getSpeaker(shotFixture1.dialogNodes[0])102      expect(result).toEqual('left')103      const result2 = getSpeaker(shotFixture2.dialogNodes[0])104      expect(result2).toEqual('right')105    })106    it('getBackgroundSlug', () => {107      const result = getBackgroundSlug(shotFixture1)108      expect(result).toEqual('background-fixture-slug')109      const result2 = getBackgroundSlug(shotFixture2)110      expect(result2).toBeUndefined()111    })112    it('getExitCharacter', () => {113      const result = getExitCharacter(shotFixture1.dialogNodes[0])114      expect(result).toEqual('both')115      const result2 = getExitCharacter(shotFixture2.dialogNodes[0])116      expect(result2).toBeUndefined()117    })118    it('getTextPosition', () => {119      const result = getTextPosition(shotFixture1.dialogNodes[0])120      expect(result).toBeUndefined()121      const result2 = getTextPosition(shotFixture2.dialogNodes[0])122      expect(result2).toEqual({123        x: 40,124        y: 10125      })126    })127    it('getText', () => {128      const result = getText(shotFixture1.dialogNodes[0])129      expect(result).toEqual('hello, world')130      const result2 = getText(shotFixture2.dialogNodes[0])131      expect(result2).toBeUndefined()132    })133    it('getCamera', () => {134      const result = getCamera(shotFixture1)135      expect(result).toEqual({ pos: { x: 2, y: 0 }, zoom: 2 })136      const result2 = getCamera(shotFixture2)137      expect(result2).toBeUndefined()138      expect(getCamera(undefined)).toBeUndefined()139    })140    it('getTextAnimationLength', () => {141      const result = getTextAnimationLength(shotFixture1.dialogNodes[1])142      expect(result).toEqual(42)143      const result2 = getTextAnimationLength(shotFixture2.dialogNodes[0])144      expect(result2).toBeUndefined()145    })146    it('getSpeakingAnimationAction', () => {147      const result = getSpeakingAnimationAction(shotFixture1.dialogNodes[1])148      expect(result).toEqual('talkyAnimation')149      const result2 = getSpeakingAnimationAction(shotFixture2.dialogNodes[0])150      expect(result2).toBeUndefined()151    })152    it('getSoundEffects', () => {153      const result = getSoundEffects(shotFixture1.dialogNodes[0])154      expect(result).toEqual([ { sound: { mp3: 'path/music' }, triggerStart: 0 } ])155      const result2 = getSoundEffects(shotFixture2.dialogNodes[0])156      expect(result2).toEqual([ { sound: { mp3: 'path/music' }, triggerStart: 30 } ])157    })158    it('getSetupMusic', () => {159      const result = getSetupMusic(shotFixture1)160      expect(result).toEqual({ ogg: 'path/music', mp3: 'path/music/mp3' })161      const result2 = getSetupMusic(shotFixture2)162      expect(result2).toBeUndefined()163    })164    it('getWaitUserInput', () => {165      expect(getWaitUserInput({ waitUserInput: false })).toEqual(false)166      expect(getWaitUserInput({})).toEqual(true)167      expect(getWaitUserInput()).toEqual(true)168      expect(getWaitUserInput({ waitUserInput: true })).toEqual(true)169    })170    it('getLanguageFilter', () => {171      expect(getLanguageFilter({})).toBeUndefined()172      expect(getLanguageFilter()).toBeUndefined()173      expect(getLanguageFilter({ programmingLanguageFilter: 'python' })).toEqual('python')174      expect(getLanguageFilter({ programmingLanguageFilter: 'javascript' })).toEqual('javascript')175    })176    it('getHeroPet', () => {177      const result = getHeroPet(shotFixture1)178      expect(result).toEqual({ slug: 'hero-dog-slug', thang: { scaleX: 1, scaleY: 2, pos: { x: 2, y: 0 } } })179      const result2 = getHeroPet(shotFixture2)180      expect(result2).toBeUndefined()181    })182  })183})184// Test for left and right character selectors.185function getCharacterThangTypeSlugTest (selector, side, data, characterProperty) {186  describe(`${side}`, () => {187    it('returns undefined when passed nothing', () => {188      expect(selector(undefined)).toBeUndefined()189    })190    it('returns undefined if the left thangType doesn\'t have type', () => {191      for (const testData of data) {192        expect(selector(testData)).toBeUndefined()193      }194    })195  })196}197// Fixture testing selectors for cinematics.198var shotFixture1 = {199  shotSetup: {200    leftThangType: {201      thangType: {202        type: 'hero',203        pos: {204          x: 3,205          y: 10206        },207        scaleX: 1,208        scaleY: 13209      },210      enterOnStart: true211    },212    rightThangType: {213      thangType: {214        type: {215          slug: 'fake-slug-thangtype'216        }217      }218    },219    heroPetThangType: {220      type: {221        slug: 'hero-dog-slug'222      },223      pos: {224        x: 2225      },226      scaleY: 2227    },228    backgroundArt: {229      type: {230        slug: 'background-fixture-slug'231      },232      pos: {233        x: 17,234        y: 18235      },236      scaleX: 0.3,237      scaleY: 0.2238    },239    camera: {240      pos: {241        x: 2242      },243      zoom: 2244    },245    music: {246      ogg: 'path/music',247      mp3: 'path/music/mp3'248    }249  },250  dialogNodes: [251    {252      dialogClear: false,253      exitCharacter: 'both',254      text: 'hello, world',255      triggers: {256        backgroundObject: {257          thangType: {258            type: {259              slug: 'background-obj-fixture'260            }261          },262          triggerStart: 1337263        },264        clearBackgroundObject: {265          triggerStart: 7331266        },267        soundFxTriggers: [268          {269            sound: {270              mp3: 'path/music'271            }272          }273        ]274      }275    },276    {277      dialogClear: false,278      textAnimationLength: 42,279      speakingAnimationAction: 'talkyAnimation'280    }281  ]282}283var shotFixture2 = {284  shotSetup: {285    rightThangType: {286      thangType: {287        type: 'hero',288        pos: {289          x: 3,290          y: 10291        },292        scaleX: 1,293        scaleY: 13294      },295      enterOnStart: true296    },297    leftThangType: {298      thangType: {299        type: {300          slug: 'fake-slug-thangtype'301        }302      }303    }304  },305  dialogNodes: [306    {307      speaker: 'right',308      triggers: {309        soundFxTriggers: [310          {311            sound: {312              mp3: 'path/music'313            },314            triggerStart: 30315          }316        ]317      },318      textLocation: {319        x: 40,320        y: 10321      }322    }323  ]...test_risk_profiler.py
Source:test_risk_profiler.py  
1from django.core.exceptions import ValidationError2from django.test import TestCase3from api.v1.tests.factories import RiskProfileAnswerFactory, RiskProfileQuestionFactory4from main.models import GoalMetric5from main.risk_profiler import recommend_risk, max_risk, MINIMUM_RISK, validate_risk_score6from main.tests.fixture import Fixture17class RiskProfilerTests(TestCase):8    def test_recommend_risk_no_questions(self):9        goal = Fixture1.goal1()10        settings = Fixture1.settings1()11        account = settings.goal.account12        self.assertEqual(recommend_risk(settings), MINIMUM_RISK)13    def test_recommend_risk_fully_unanswered(self):14        # Populate the questions, we should still get 0.515        goal = Fixture1.goal1()16        settings = Fixture1.settings1()17        account = settings.goal.account18        Fixture1.populate_risk_profile_questions()19        self.assertEqual(recommend_risk(settings), MINIMUM_RISK)20    def test_recommend_risk_partially_unanswered(self):21        # Partially populate the answers, we should still get 0.522        goal = Fixture1.goal1()23        settings = Fixture1.settings1()24        account = settings.goal.account25        Fixture1.populate_risk_profile_questions()26        Fixture1.risk_profile_answer1a()27        self.assertEqual(recommend_risk(settings), MINIMUM_RISK)28    def test_recommend_risk_fully_answered_bad_questions(self):29        # Fully populate the answers, but no range in the available question responses, we should get 0.530        goal = Fixture1.goal1()31        settings = Fixture1.settings1()32        account = settings.goal.account33        Fixture1.populate_risk_profile_questions()  # Also populates all possible answers.34        Fixture1.populate_risk_profile_responses()35        Fixture1.risk_profile_question3()  # Add a question we don't have an answer for36        self.assertEqual(recommend_risk(settings), MINIMUM_RISK)37        # Now answer the question, we shouldn't get MINIMUM_RISK38        account.primary_owner.risk_profile_responses.add(Fixture1.risk_profile_answer3a())39        self.assertNotEqual(recommend_risk(settings), MINIMUM_RISK)40    def test_fully_answered_zero_max(self):41        goal = Fixture1.goal1()42        setting = Fixture1.settings1()43        risk_metric = setting.metric_group.metrics.get(type=GoalMetric.METRIC_TYPE_RISK_SCORE)44        q = RiskProfileQuestionFactory.create(group=goal.account.primary_owner.risk_profile_group)45        a = RiskProfileAnswerFactory.create(b_score=0, a_score=0, s_score=0, question=q)46        client = goal.account.primary_owner47        client.risk_profile_responses.add(a)48        self.assertGreater(risk_metric.configured_val, 0.01)49        with self.assertRaises(ValidationError) as ex:50            validate_risk_score(setting)51        risk_metric.configured_val = 052        risk_metric.save()53        self.assertEqual(validate_risk_score(setting), None)  # Should now complete OK.54        self.assertEqual(max_risk(setting), 0.0)55        self.assertEqual(recommend_risk(setting), 0.0)56    def test_recommend_risk_fully_answered(self):57        # Fully populate the answers, we should get 0.558        goal = Fixture1.goal1()59        settings = Fixture1.settings1()60        Fixture1.populate_risk_profile_questions()  # Also populates all possible answers.61        Fixture1.populate_risk_profile_responses()62        self.assertEqual(recommend_risk(settings), 1.0)63    def test_recommend_risk_no_weights(self):64        goal = Fixture1.goal1()65        settings = Fixture1.settings1()66        self.assertEqual(recommend_risk(settings), MINIMUM_RISK)67    def test_recommend_risk(self):68        goal = Fixture1.goal1()69        settings = Fixture1.settings1()70        client = goal.account.primary_owner71        # Add the weights for the risk factors72        Fixture1.populate_risk_profile_questions()  # Also populates all possible answers.73        Fixture1.populate_risk_profile_responses()74        # First lets start with the test_client, who scored 9 for all B,A,S75        # A goal of 80% of the value on a all-9s account is a bad idea76        # It's the lowest possible score77        settings.goal.account.primary_owner.net_worth = 10078        settings.goal.cash_balance = 8079        self.assertAlmostEqual(recommend_risk(settings), 0.10, 2)80        # A goal of 50% of the value is just as bad81        settings.goal.account.primary_owner.net_worth = 10082        settings.goal.cash_balance = 5083        self.assertAlmostEqual(recommend_risk(settings), 0.10, 2)84        # A goal of 10% of the value on a all-9s account is 1.085        # meaning this is the safest possible bet86        settings.goal.account.primary_owner.net_worth = 10087        settings.goal.cash_balance = 1088        self.assertAlmostEqual(recommend_risk(settings), 1.0, 2)89        # A goal of 33% of the value on a all-9s account is about 0.590        # Even if you are risky, sophisticated and rich, 30% is a lot91        settings.goal.account.primary_owner.net_worth = 10092        settings.goal.cash_balance = 3393        self.assertAlmostEqual(recommend_risk(settings), 0.5, 1)94        # For a new investor, the best possible suggestion is 10% or less95        settings.goal.account.primary_owner.net_worth = 10096        settings.goal.cash_balance = 1097        client.risk_profile_responses.clear()98        client.risk_profile_responses.add(Fixture1.risk_profile_answer1b())99        client.risk_profile_responses.add(Fixture1.risk_profile_answer2b())100        self.assertAlmostEqual(recommend_risk(settings), 0.2, 1)101    def test_max_risk(self):102        goal = Fixture1.goal1()103        settings = Fixture1.settings1()104        client = goal.account.primary_owner105        # Add the weights for the risk factors106        Fixture1.populate_risk_profile_questions()  # Also populates all possible answers.107        Fixture1.populate_risk_profile_responses()108        # we haven't set a net worth or a target, so worth_score isn't a factor109        # An all-9s account will have a max_risk of 1110        self.assertEqual(max_risk(settings), 1.0)111        # and if they are low risk behavior, high Ability + Sophistication112        # the max risk is still 1113        client.risk_profile_responses.clear()114        client.risk_profile_responses.add(Fixture1.risk_profile_answer1c())115        client.risk_profile_responses.add(Fixture1.risk_profile_answer2c())116        self.assertEqual(max_risk(settings), 1.0)117        # but if they are risky, new and unskilled, recommend no risk118        client.risk_profile_responses.clear()119        client.risk_profile_responses.add(Fixture1.risk_profile_answer1d())120        client.risk_profile_responses.add(Fixture1.risk_profile_answer2d())121        self.assertAlmostEqual(recommend_risk(settings), 0.1, 1)...read-frontmatter.js
Source:read-frontmatter.js  
1import parse from '../../lib/read-frontmatter.js'2const filepath = 'path/to/file.md'3const fixture1 = `---4title: Hello, World5meaning_of_life: 426---7I am content.8`9describe('frontmatter', () => {10  it('parses frontmatter and content in a given string (no options required)', () => {11    const { data, content, errors } = parse(fixture1)12    expect(data.title).toBe('Hello, World')13    expect(data.meaning_of_life).toBe(42)14    expect(content.trim()).toBe('I am content.')15    expect(errors.length).toBe(0)16  })17  describe('frontmatter.stringify', () => {18    it('is exported', () => {19      expect(typeof parse.stringify).toBe('function')20    })21  })22  describe('YML parsing errors', () => {23    it('creates errors if YML has an unescaped quote', () => {24      const fixture = `---25intro: 'I've got an unescaped quote'26---27I am content.28`29      const { errors } = parse(fixture, { filepath })30      expect(errors.length).toBe(1)31      const expectedError = {32        filepath: 'path/to/file.md',33        message: 'YML parsing error!',34        reason: 'invalid frontmatter entry',35      }36      expect(errors[0]).toEqual(expectedError)37    })38    it('creates errors if YML has incorrect indentation', () => {39      const fixture = `---40title: Hello, World41 intro: 'I have a bad leading space'42---43I am content.44`45      const { errors } = parse(fixture, { filepath })46      expect(errors.length).toBe(1)47      const expectedError = {48        filepath: 'path/to/file.md',49        message: 'YML parsing error!',50        reason: 'bad indentation of a mapping entry',51      }52      expect(errors[0]).toEqual(expectedError)53    })54  })55  describe('schema', () => {56    it('is optional', () => {57      const schema = {58        properties: {59          title: {60            type: 'string',61          },62          meaning_of_life: {63            type: 'number',64          },65        },66      }67      const { data, content, errors } = parse(fixture1, { schema })68      expect(data.title).toBe('Hello, World')69      expect(data.meaning_of_life).toBe(42)70      expect(content.trim()).toBe('I am content.')71      expect(errors.length).toBe(0)72    })73    it('creates errors if frontmatter does not conform to schema', () => {74      const schema = {75        properties: {76          meaning_of_life: {77            type: 'number',78            minimum: 50,79          },80        },81      }82      const { data, content, errors } = parse(fixture1, { schema })83      expect(data.title).toBe('Hello, World')84      expect(data.meaning_of_life).toBe(42)85      expect(content.trim()).toBe('I am content.')86      expect(errors.length).toBe(1)87      const expectedError = {88        attribute: 'minimum',89        property: 'meaning_of_life',90        expected: 50,91        actual: 42,92        message: 'must be greater than or equal to 50',93      }94      expect(errors[0]).toEqual(expectedError)95    })96    it('creates errors if required frontmatter is not present', () => {97      const schema = {98        properties: {99          yet_another_key: {100            type: 'string',101            required: true,102          },103        },104      }105      const { errors } = parse(fixture1, { schema })106      expect(errors.length).toBe(1)107      const expectedError = {108        attribute: 'required',109        property: 'yet_another_key',110        expected: true,111        actual: undefined,112        message: 'is required',113      }114      expect(errors[0]).toEqual(expectedError)115    })116  })117  describe('validateKeyNames', () => {118    const schema = {119      properties: {120        age: {121          type: 'number',122        },123      },124    }125    it('creates errors for undocumented keys if `validateKeyNames` is true', () => {126      const { errors } = parse(fixture1, { schema, validateKeyNames: true, filepath })127      expect(errors.length).toBe(2)128      const expectedErrors = [129        {130          property: 'title',131          message: 'not allowed. Allowed properties are: age',132          filepath: 'path/to/file.md',133        },134        {135          property: 'meaning_of_life',136          message: 'not allowed. Allowed properties are: age',137          filepath: 'path/to/file.md',138        },139      ]140      expect(errors).toEqual(expectedErrors)141    })142    it('does not create errors for undocumented keys if `validateKeyNames` is false', () => {143      const { errors } = parse(fixture1, { schema, validateKeyNames: false })144      expect(errors.length).toBe(0)145    })146  })147  describe('validateKeyOrder', () => {148    it('creates errors if `validateKeyOrder` is true and keys are not in order', () => {149      const schema = {150        properties: {151          meaning_of_life: {152            type: 'number',153          },154          title: {155            type: 'string',156          },157        },158      }159      const { errors } = parse(fixture1, { schema, validateKeyOrder: true, filepath })160      const expectedErrors = [161        {162          property: 'keys',163          message:164            'keys must be in order. Current: title,meaning_of_life; Expected: meaning_of_life,title',165          filepath: 'path/to/file.md',166        },167      ]168      expect(errors).toEqual(expectedErrors)169    })170    it('does not create errors if `validateKeyOrder` is true and keys are in order', () => {171      const schema = {172        properties: {173          title: {174            type: 'string',175          },176          meaning_of_life: {177            type: 'number',178          },179        },180      }181      const { errors } = parse(fixture1, { schema, validateKeyOrder: true })182      expect(errors.length).toBe(0)183    })184    it('does not create errors if `validateKeyOrder` is true and expected keys are in order', () => {185      const schema = {186        properties: {187          title: {188            type: 'string',189            required: true,190          },191          yet_another_key: {192            type: 'string',193          },194          meaning_of_life: {195            type: 'number',196            required: true,197          },198        },199      }200      const { errors } = parse(fixture1, { schema, validateKeyOrder: true })201      expect(errors.length).toBe(0)202    })203  })...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
