restructured context
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
import type {
|
import type {
|
||||||
|
Entitlement,
|
||||||
FeatureOptions,
|
FeatureOptions,
|
||||||
FullCusProduct,
|
FullCusProduct,
|
||||||
FullProduct,
|
FullProduct,
|
||||||
|
Price,
|
||||||
} from "@autumn/shared";
|
} from "@autumn/shared";
|
||||||
import type { FullCustomer } from "@shared/models/cusModels/fullCusModel";
|
import type { FullCustomer } from "@shared/models/cusModels/fullCusModel";
|
||||||
import type Stripe from "stripe";
|
import type Stripe from "stripe";
|
||||||
@@ -32,6 +34,10 @@ export interface BillingContext {
|
|||||||
|
|
||||||
// Feature quantities
|
// Feature quantities
|
||||||
featureQuantities: FeatureOptions[];
|
featureQuantities: FeatureOptions[];
|
||||||
|
|
||||||
|
// Unforunately, need to add custom prices, custom entitlements and free trial here, because it's determined in the setup step.
|
||||||
|
customPrices: Price[];
|
||||||
|
customEnts: Entitlement[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateSubscriptionBillingContext extends BillingContext {
|
export interface UpdateSubscriptionBillingContext extends BillingContext {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { FullProduct, ProductItem } from "@autumn/shared";
|
import type { FullProduct, ProductItem } from "@autumn/shared";
|
||||||
import type { AutumnContext } from "../../../../../honoUtils/HonoEnv";
|
import type { AutumnContext } from "@/honoUtils/HonoEnv";
|
||||||
import { getEntsWithFeature } from "../../../../products/entitlements/entitlementUtils";
|
import { getEntsWithFeature } from "@/internal/products/entitlements/entitlementUtils";
|
||||||
import { handleNewProductItems } from "../../../../products/product-items/productItemUtils/handleNewProductItems";
|
import { handleNewProductItems } from "@/internal/products/product-items/productItemUtils/handleNewProductItems";
|
||||||
|
|
||||||
export const computeCustomFullProduct = async ({
|
export const setupCustomFullProduct = async ({
|
||||||
ctx,
|
ctx,
|
||||||
customItems,
|
customItems,
|
||||||
currentFullProduct,
|
currentFullProduct,
|
||||||
@@ -11,10 +11,10 @@ import type { AutumnContext } from "@/honoUtils/HonoEnv";
|
|||||||
import { paramsToFeatureOptions } from "@/internal/billing/v2/compute/computeAutumnUtils/paramsToFeatureOptions";
|
import { paramsToFeatureOptions } from "@/internal/billing/v2/compute/computeAutumnUtils/paramsToFeatureOptions";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses feature quantities from params, iterating over all prepaid prices.
|
* Sets up feature quantities context from params, iterating over all prepaid prices.
|
||||||
* For each prepaid price, uses new quantity from params or falls back to existing subscription.
|
* For each prepaid price, uses new quantity from params or falls back to existing subscription.
|
||||||
*/
|
*/
|
||||||
export const parseFeatureQuantitiesParams = ({
|
export const setupFeatureQuantitiesContext = ({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams,
|
featureQuantitiesParams,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import type { UpdateSubscriptionV0Params } from "@autumn/shared";
|
||||||
|
import type { AutumnContext } from "@server/honoUtils/HonoEnv";
|
||||||
|
import { CusService } from "@server/internal/customers/CusService";
|
||||||
|
|
||||||
|
export const setupFullCustomerContext = async ({
|
||||||
|
ctx,
|
||||||
|
params,
|
||||||
|
autoCreateCustomer = false,
|
||||||
|
}: {
|
||||||
|
ctx: AutumnContext;
|
||||||
|
params: UpdateSubscriptionV0Params;
|
||||||
|
autoCreateCustomer?: boolean;
|
||||||
|
}) => {
|
||||||
|
const { db, org, env } = ctx;
|
||||||
|
const { customer_id: customerId } = params;
|
||||||
|
|
||||||
|
const fullCustomer = await CusService.getFull({
|
||||||
|
db,
|
||||||
|
idOrInternalId: customerId,
|
||||||
|
orgId: org.id,
|
||||||
|
env,
|
||||||
|
withSubs: true,
|
||||||
|
withEntities: true,
|
||||||
|
entityId: params.entity_id ?? undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return fullCustomer;
|
||||||
|
};
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
CusProductStatus,
|
CusProductStatus,
|
||||||
cusProductToProduct,
|
|
||||||
type UpdateSubscriptionV0Params,
|
type UpdateSubscriptionV0Params,
|
||||||
} from "@autumn/shared";
|
} from "@autumn/shared";
|
||||||
import type { AutumnContext } from "@server/honoUtils/HonoEnv";
|
import type { AutumnContext } from "@server/honoUtils/HonoEnv";
|
||||||
@@ -9,8 +8,6 @@ import { buildAutumnLineItems } from "@/internal/billing/v2/compute/computeAutum
|
|||||||
import type { AutumnBillingPlan } from "@/internal/billing/v2/types/billingPlan";
|
import type { AutumnBillingPlan } from "@/internal/billing/v2/types/billingPlan";
|
||||||
import { computeCustomPlanFreeTrial } from "@/internal/billing/v2/updateSubscription/compute/customPlan/computeCustomPlanFreeTrial";
|
import { computeCustomPlanFreeTrial } from "@/internal/billing/v2/updateSubscription/compute/customPlan/computeCustomPlanFreeTrial";
|
||||||
import { computeCustomPlanNewCustomerProduct } from "@/internal/billing/v2/updateSubscription/compute/customPlan/computeCustomPlanNewCustomerProduct";
|
import { computeCustomPlanNewCustomerProduct } from "@/internal/billing/v2/updateSubscription/compute/customPlan/computeCustomPlanNewCustomerProduct";
|
||||||
import { parseFeatureQuantitiesParams } from "@/internal/billing/v2/utils/parseFeatureQuantitiesParams";
|
|
||||||
import { computeCustomFullProduct } from "../../../compute/computeAutumnUtils/computeCustomFullProduct";
|
|
||||||
|
|
||||||
export const computeCustomPlan = async ({
|
export const computeCustomPlan = async ({
|
||||||
ctx,
|
ctx,
|
||||||
@@ -21,23 +18,10 @@ export const computeCustomPlan = async ({
|
|||||||
updateSubscriptionContext: UpdateSubscriptionBillingContext;
|
updateSubscriptionContext: UpdateSubscriptionBillingContext;
|
||||||
params: UpdateSubscriptionV0Params;
|
params: UpdateSubscriptionV0Params;
|
||||||
}) => {
|
}) => {
|
||||||
const { customerProduct } = updateSubscriptionContext;
|
const { customerProduct, customPrices, customEnts } =
|
||||||
|
updateSubscriptionContext;
|
||||||
|
|
||||||
const currentFullProduct = cusProductToProduct({
|
const customFullProduct = updateSubscriptionContext.fullProducts[0];
|
||||||
cusProduct: customerProduct,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
|
||||||
fullProduct: customFullProduct,
|
|
||||||
customPrices,
|
|
||||||
customEnts,
|
|
||||||
} = await computeCustomFullProduct({
|
|
||||||
ctx,
|
|
||||||
currentFullProduct,
|
|
||||||
customItems: params.items,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateSubscriptionContext.fullProducts = [customFullProduct];
|
|
||||||
|
|
||||||
// 2. Compute the custom trial details
|
// 2. Compute the custom trial details
|
||||||
const { freeTrialPlan, customFreeTrial } = computeCustomPlanFreeTrial({
|
const { freeTrialPlan, customFreeTrial } = computeCustomPlanFreeTrial({
|
||||||
@@ -50,13 +34,6 @@ export const computeCustomPlan = async ({
|
|||||||
updateSubscriptionContext.billingCycleAnchorMs = freeTrialPlan.trialEndsAt;
|
updateSubscriptionContext.billingCycleAnchorMs = freeTrialPlan.trialEndsAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSubscriptionContext.featureQuantities = parseFeatureQuantitiesParams({
|
|
||||||
ctx,
|
|
||||||
featureQuantitiesParams: params,
|
|
||||||
fullProduct: customFullProduct,
|
|
||||||
currentCustomerProduct: customerProduct,
|
|
||||||
}); // re-parse feature quantities for new custom product
|
|
||||||
|
|
||||||
// 3. Compute the new customer product
|
// 3. Compute the new customer product
|
||||||
const newFullCustomerProduct = computeCustomPlanNewCustomerProduct({
|
const newFullCustomerProduct = computeCustomPlanNewCustomerProduct({
|
||||||
ctx,
|
ctx,
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
import {
|
import { secondsToMs, type UpdateSubscriptionV0Params } from "@autumn/shared";
|
||||||
cusProductToProduct,
|
|
||||||
InternalError,
|
|
||||||
secondsToMs,
|
|
||||||
type UpdateSubscriptionV0Params,
|
|
||||||
} from "@autumn/shared";
|
|
||||||
import type { AutumnContext } from "@/honoUtils/HonoEnv";
|
import type { AutumnContext } from "@/honoUtils/HonoEnv";
|
||||||
import { setupStripeBillingContext } from "@/internal/billing/v2/providers/stripe/setup/setupStripeBillingContext";
|
import { setupStripeBillingContext } from "@/internal/billing/v2/providers/stripe/setup/setupStripeBillingContext";
|
||||||
import { CusService } from "../../../../customers/CusService";
|
import { setupFeatureQuantitiesContext } from "@/internal/billing/v2/setup/setupFeatureQuantitiesContext";
|
||||||
|
import { setupFullCustomerContext } from "@/internal/billing/v2/setup/setupFullCustomerContext";
|
||||||
|
import { setupUpdateSubscriptionProductContext } from "@/internal/billing/v2/updateSubscription/setup/setupUpdateSubscriptionProductContext";
|
||||||
import type { UpdateSubscriptionBillingContext } from "../../billingContext";
|
import type { UpdateSubscriptionBillingContext } from "../../billingContext";
|
||||||
import { parseFeatureQuantitiesParams } from "../../utils/parseFeatureQuantitiesParams";
|
|
||||||
import { findTargetCustomerProduct } from "./findTargetCustomerProduct";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the context for updating a subscription
|
* Fetch the context for updating a subscription
|
||||||
@@ -24,32 +19,23 @@ export const setupUpdateSubscriptionBillingContext = async ({
|
|||||||
ctx: AutumnContext;
|
ctx: AutumnContext;
|
||||||
params: UpdateSubscriptionV0Params;
|
params: UpdateSubscriptionV0Params;
|
||||||
}): Promise<UpdateSubscriptionBillingContext> => {
|
}): Promise<UpdateSubscriptionBillingContext> => {
|
||||||
const { db, org, env } = ctx;
|
const fullCustomer = await setupFullCustomerContext({
|
||||||
const { customer_id: customerId, product_id: productId } = params;
|
ctx,
|
||||||
|
|
||||||
const fullCustomer = await CusService.getFull({
|
|
||||||
db,
|
|
||||||
idOrInternalId: customerId,
|
|
||||||
orgId: org.id,
|
|
||||||
env,
|
|
||||||
withSubs: true,
|
|
||||||
withEntities: true,
|
|
||||||
entityId: params.entity_id ?? undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const targetCustomerProduct = findTargetCustomerProduct({
|
|
||||||
params,
|
params,
|
||||||
fullCustomer,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!targetCustomerProduct) {
|
const { customerProduct, fullProduct, customPrices, customEnts } =
|
||||||
throw new InternalError({
|
await setupUpdateSubscriptionProductContext({
|
||||||
message: `[API Subscription Update] Target customer product not found: ${productId}`,
|
ctx,
|
||||||
|
fullCustomer,
|
||||||
|
params,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const fullProduct = cusProductToProduct({
|
const featureQuantities = setupFeatureQuantitiesContext({
|
||||||
cusProduct: targetCustomerProduct,
|
ctx,
|
||||||
|
featureQuantitiesParams: params,
|
||||||
|
fullProduct,
|
||||||
|
currentCustomerProduct: customerProduct,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -61,14 +47,7 @@ export const setupUpdateSubscriptionBillingContext = async ({
|
|||||||
} = await setupStripeBillingContext({
|
} = await setupStripeBillingContext({
|
||||||
ctx,
|
ctx,
|
||||||
fullCustomer,
|
fullCustomer,
|
||||||
targetCustomerProduct,
|
targetCustomerProduct: customerProduct,
|
||||||
});
|
|
||||||
|
|
||||||
const featureQuantities = parseFeatureQuantitiesParams({
|
|
||||||
ctx,
|
|
||||||
featureQuantitiesParams: params,
|
|
||||||
fullProduct,
|
|
||||||
currentCustomerProduct: targetCustomerProduct,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentEpochMs = testClockFrozenTime ?? Date.now();
|
const currentEpochMs = testClockFrozenTime ?? Date.now();
|
||||||
@@ -88,7 +67,7 @@ export const setupUpdateSubscriptionBillingContext = async ({
|
|||||||
return {
|
return {
|
||||||
fullCustomer,
|
fullCustomer,
|
||||||
fullProducts: [fullProduct],
|
fullProducts: [fullProduct],
|
||||||
customerProduct: targetCustomerProduct,
|
customerProduct,
|
||||||
stripeSubscription,
|
stripeSubscription,
|
||||||
stripeSubscriptionSchedule,
|
stripeSubscriptionSchedule,
|
||||||
stripeCustomer,
|
stripeCustomer,
|
||||||
@@ -98,5 +77,8 @@ export const setupUpdateSubscriptionBillingContext = async ({
|
|||||||
billingCycleAnchorMs: billingCycleAnchorMs ?? "now",
|
billingCycleAnchorMs: billingCycleAnchorMs ?? "now",
|
||||||
invoiceMode,
|
invoiceMode,
|
||||||
featureQuantities,
|
featureQuantities,
|
||||||
|
|
||||||
|
customPrices,
|
||||||
|
customEnts,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
cusProductToProduct,
|
||||||
|
type FullCustomer,
|
||||||
|
InternalError,
|
||||||
|
type UpdateSubscriptionV0Params,
|
||||||
|
} from "@autumn/shared";
|
||||||
|
import type { AutumnContext } from "@/honoUtils/HonoEnv";
|
||||||
|
import { setupCustomFullProduct } from "../../setup/setupCustomFullProduct";
|
||||||
|
import { findTargetCustomerProduct } from "./findTargetCustomerProduct";
|
||||||
|
|
||||||
|
export const setupUpdateSubscriptionProductContext = async ({
|
||||||
|
ctx,
|
||||||
|
fullCustomer,
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
ctx: AutumnContext;
|
||||||
|
fullCustomer: FullCustomer;
|
||||||
|
params: UpdateSubscriptionV0Params;
|
||||||
|
}) => {
|
||||||
|
const targetCustomerProduct = findTargetCustomerProduct({
|
||||||
|
params,
|
||||||
|
fullCustomer,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!targetCustomerProduct) {
|
||||||
|
throw new InternalError({
|
||||||
|
message: `[API Subscription Update] Target customer product not found: ${params.product_id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullProduct = cusProductToProduct({
|
||||||
|
cusProduct: targetCustomerProduct,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
fullProduct: customFullProduct,
|
||||||
|
customPrices,
|
||||||
|
customEnts,
|
||||||
|
} = await setupCustomFullProduct({
|
||||||
|
ctx,
|
||||||
|
currentFullProduct: fullProduct,
|
||||||
|
customItems: params.items,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
customerProduct: targetCustomerProduct,
|
||||||
|
fullProduct: customFullProduct,
|
||||||
|
customPrices,
|
||||||
|
customEnts,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -12,7 +12,7 @@ import { isFreeProduct, isOneOff } from "@/internal/products/productUtils.js";
|
|||||||
import RecaseError from "@/utils/errorUtils.js";
|
import RecaseError from "@/utils/errorUtils.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use parseFeatureQuantitiesParams from billing/v2/utils instead
|
* @deprecated Use setupFeatureQuantitiesContext from billing/v2/setup instead
|
||||||
*/
|
*/
|
||||||
export const mapOptionsList = ({
|
export const mapOptionsList = ({
|
||||||
optionsInput,
|
optionsInput,
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import {
|
|||||||
} from "@tests/utils/mockUtils/priceMocks";
|
} from "@tests/utils/mockUtils/priceMocks";
|
||||||
import { createMockFullProduct } from "@tests/utils/mockUtils/productMocks";
|
import { createMockFullProduct } from "@tests/utils/mockUtils/productMocks";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { parseFeatureQuantitiesParams } from "@/internal/billing/v2/utils/parseFeatureQuantitiesParams";
|
import { setupFeatureQuantitiesContext } from "@/internal/billing/v2/setup/setupFeatureQuantitiesContext";
|
||||||
|
|
||||||
// ============ TESTS ============
|
// ============ TESTS ============
|
||||||
|
|
||||||
describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
describe(chalk.yellowBright("setupFeatureQuantitiesContext"), () => {
|
||||||
describe("basic quantity inheritance", () => {
|
describe("basic quantity inheritance", () => {
|
||||||
test("1. current has quantity, new params has none → uses current", () => {
|
test("1. current has quantity, new params has none → uses current", () => {
|
||||||
const feature = createMockFeature({
|
const feature = createMockFeature({
|
||||||
@@ -47,7 +47,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -81,7 +81,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -123,7 +123,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -203,7 +203,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
features: [creditsFeature, seatsFeature, storageFeature],
|
features: [creditsFeature, seatsFeature, storageFeature],
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -246,7 +246,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -282,7 +282,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -317,7 +317,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -373,7 +373,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -429,7 +429,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -477,7 +477,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -517,7 +517,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -542,7 +542,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [] });
|
const ctx = createMockCtx({ features: [] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -570,7 +570,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
const ctx = createMockCtx({ features: [] });
|
const ctx = createMockCtx({ features: [] });
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
parseFeatureQuantitiesParams({
|
setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -601,7 +601,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -643,7 +643,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -686,7 +686,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
@@ -731,7 +731,7 @@ describe(chalk.yellowBright("parseFeatureQuantitiesParams"), () => {
|
|||||||
|
|
||||||
const ctx = createMockCtx({ features: [feature] });
|
const ctx = createMockCtx({ features: [feature] });
|
||||||
|
|
||||||
const result = parseFeatureQuantitiesParams({
|
const result = setupFeatureQuantitiesContext({
|
||||||
ctx,
|
ctx,
|
||||||
featureQuantitiesParams: params,
|
featureQuantitiesParams: params,
|
||||||
fullProduct,
|
fullProduct,
|
||||||
|
|||||||
Reference in New Issue
Block a user