diff --git a/e2e/src/componentsController.spec.ts b/e2e/src/componentsController.spec.ts index 2d770ac..af09222 100644 --- a/e2e/src/componentsController.spec.ts +++ b/e2e/src/componentsController.spec.ts @@ -1,8 +1,12 @@ import { + ComponentPricePointsController, ComponentsController, + CreateComponentPricePointRequest, + CreateComponentPricePointRequestPricePoint, CreateMeteredComponent, CreateOrUpdateProductRequest, IntervalUnit, + Price, PricingScheme, ProductFamiliesController, ProductFamily, @@ -17,6 +21,8 @@ describe('Components Controller', () => { let componentsController: ComponentsController; let productsController: ProductsController; let invalidComponentsController: ComponentsController; + let componentPricePointsController: ComponentPricePointsController; + let invalidComponentPricePointsController: ComponentPricePointsController; beforeAll(async () => { const client = createClient(); @@ -24,6 +30,10 @@ describe('Components Controller', () => { const productFamiliesController = new ProductFamiliesController(client); invalidComponentsController = new ComponentsController(invalidClient); componentsController = new ComponentsController(client); + componentPricePointsController = new ComponentPricePointsController(client); + invalidComponentPricePointsController = new ComponentPricePointsController( + invalidClient + ); productsController = new ProductsController(client); productFamily = ( @@ -40,7 +50,7 @@ describe('Components Controller', () => { const prepareDataForComponentResponse = async ( productPaload: CreateOrUpdateProductRequest, - productFamilyId: number, + productFamilyId: string, componentPayload: CreateMeteredComponent ) => { await productsController.createProduct( @@ -49,7 +59,7 @@ describe('Components Controller', () => { ); const createComponentReponse = - await componentsController.createMeteredComponent(productFamilyId.toString(), { + await componentsController.createMeteredComponent(productFamilyId, { ...componentPayload, }); @@ -88,7 +98,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -133,7 +143,7 @@ describe('Components Controller', () => { await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -177,7 +187,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -225,7 +235,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); const componentId = component.id?.toString() || ''; @@ -276,7 +286,7 @@ describe('Components Controller', () => { await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -321,7 +331,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); const componentId = component.id?.toString() || ''; @@ -339,7 +349,7 @@ describe('Components Controller', () => { }); }); - describe('Update Product Family Component', () => { + describe('Update Component', () => { it('should update component with valid id', async () => { const newProductPayload: CreateOrUpdateProductRequest = { product: { @@ -378,7 +388,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -425,7 +435,7 @@ describe('Components Controller', () => { await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -475,7 +485,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -528,7 +538,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -572,7 +582,7 @@ describe('Components Controller', () => { await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -617,7 +627,7 @@ describe('Components Controller', () => { const { component } = await prepareDataForComponentResponse( newProductPayload, - productFamilyId, + productFamilyId.toString(), meteredComponent ); @@ -636,4 +646,462 @@ describe('Components Controller', () => { }); }); }); + describe('List Components', () => { + it('should list components', async () => { + const componentsControllerResponse = + await componentsController.listComponents({}); + + expect(componentsControllerResponse.statusCode).toBe(200); + }); + it('should not list components with invalid credentials', async () => { + const invalidcomponentsControllerResponse = + invalidComponentsController.listComponents({}); + + expect(invalidcomponentsControllerResponse).rejects.toThrow(); + + await invalidcomponentsControllerResponse.catch((reason) => { + expect(reason.statusCode).toBe(401); + }); + }); + }); + describe('List Components for product family', () => { + it('should list components associated with the specifed product family', async () => { + const productFamilyId = productFamily?.id || 0; + + const componentsControllerResponse = + await componentsController.listComponentsForProductFamily({ + productFamilyId, + }); + + expect(componentsControllerResponse.statusCode).toBe(200); + }); + it('should list components associated with the specifed product family', async () => { + const invalidProductFamilyId = 123; + const listComponentsForProductFamilyResponse = + componentsController.listComponentsForProductFamily({ + productFamilyId: invalidProductFamilyId, + }); + + expect(listComponentsForProductFamilyResponse).rejects.toThrow(); + + await listComponentsForProductFamilyResponse.catch((reason) => { + expect(reason.statusCode).toBe(404); + }); + }); + it('should not list components associated with the specifed product family with invalid credentials', async () => { + const productFamilyId = productFamily?.id || 0; + + const componentsControllerResponse = + invalidComponentsController.listComponentsForProductFamily({ + productFamilyId, + }); + + expect(componentsControllerResponse).rejects.toThrow(); + + await componentsControllerResponse.catch((reason) => { + expect(reason.statusCode).toBe(401); + }); + }); + }); + describe('Update Product Family Component', () => { + it('should update product family component with valid id', async () => { + const newProductPayload: CreateOrUpdateProductRequest = { + product: { + name: `update-product-family-component-name-${uid()}`, + handle: `update-product-family-component-name-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + + const productFamilyId = productFamily?.id || 0; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `update-product-family-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + const updatedMeteredComponent: UpdateComponentRequest = { + component: { + name: 'updated-product-family-component-name', + description: 'updated-description', + }, + }; + + const { component } = await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + const componentId = component.id?.toString() || ''; + + const updateComponentResponse = + await componentsController.updateProductFamilyComponent( + productFamilyId, + componentId, + updatedMeteredComponent + ); + + expect(updateComponentResponse.statusCode).toBe(200); + expect(updateComponentResponse.result.component.name).toBe( + updatedMeteredComponent.component.name + ); + }); + it('should not update product family component with invalid id', async () => { + const newProductPayload = { + product: { + name: `update-product-family-component-invalid-id-${uid()}`, + handle: `update-product-family-component-invalid-id-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + const productFamilyId = productFamily?.id || 0; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `update-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + const updateComponentResponse = + componentsController.updateProductFamilyComponent( + productFamilyId, + invalidComponentId, + { + component: { + name: 'updated-product-family-component-name-with-invalid-id', + description: 'updated-description-with-invalid-id', + }, + } + ); + + expect(updateComponentResponse).rejects.toThrow(); + + await updateComponentResponse.catch((reason) => { + expect(reason.statusCode).toBe(404); + }); + }); + it('should not update product family component with invalid credentials', async () => { + const newProductPayload = { + product: { + name: `update-product-family-component-with-invalid-credentials-${uid()}`, + handle: `update-product-family-component-with-invalid-credentials-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + const productFamilyId = productFamily?.id || 0; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `update-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + const { component } = await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + const componentId = component.id?.toString() || ''; + + const updateComponentResponse = + invalidComponentsController.updateProductFamilyComponent( + productFamilyId, + componentId, + { + component: { + name: `updated-product-family-component-name-with-invalid-credentials-${uid()}`, + description: `updated-product-family-component-description-with-invalid-credentials-${uid()}`, + }, + } + ); + + expect(updateComponentResponse).rejects.toThrow(); + + await updateComponentResponse.catch((reason) => { + expect(reason.statusCode).toBe(401); + }); + }); + }); + describe('Promote Component Price Point to default', () => { + it('should promote component price to default', async () => { + const newProductPayload: CreateOrUpdateProductRequest = { + product: { + name: `promote-component-price-to-default-name-${uid()}`, + handle: `promote-component-price-to-default-handle-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + + const price: Price = { + starting_quantity: '1', + ending_quantity: '', + unit_price: '1', + startingQuantity: '', + unitPrice: '', + }; + + const productFamilyId = productFamily?.id || 0; + + const createComponentPricePointRequestPricePoint: CreateComponentPricePointRequestPricePoint = + { + name: `price-point-name-${uid()}`, + handle: `price-point-handle-${uid()}`, + prices: [price], + pricing_scheme: 'per_unit', + tax_included: false, + pricingScheme: PricingScheme.PerUnit, + overagePricing: [], + }; + + const pricePoint: CreateComponentPricePointRequest = { + pricePoint: createComponentPricePointRequestPricePoint, + }; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `promote-component-price-to-default-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + const { component } = await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + const createComponentPricePointResponse = + await componentPricePointsController.createComponentPricePoint( + component.id || 0, + pricePoint + ); + + const pricePointId = + createComponentPricePointResponse.result.pricePoint?.id || 0; + + const promoteComponentPricePointToDefaultResponse = + await componentPricePointsController.promoteComponentPricePointToDefault( + component.id || 0, + pricePointId + ); + + expect(promoteComponentPricePointToDefaultResponse.statusCode).toBe(200); + expect( + promoteComponentPricePointToDefaultResponse.result.component + .defaultPricePointId + ).toBe(pricePointId); + }); + + it('should not promote component price to default with invalid price point id', async () => { + const newProductPayload: CreateOrUpdateProductRequest = { + product: { + name: `promote-component-price-to-default-name-${uid()}`, + handle: `promote-component-price-to-default-handle-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + + const price: Price = { + starting_quantity: '1', + ending_quantity: '', + unit_price: '1', + startingQuantity: '', + unitPrice: '', + }; + + const productFamilyId = productFamily?.id || 0; + + const createComponentPricePointRequestPricePoint: CreateComponentPricePointRequestPricePoint = + { + name: `price-point-name-${uid()}`, + handle: `price-point-handle-${uid()}`, + prices: [price], + pricing_scheme: 'per_unit', + tax_included: false, + pricingScheme: PricingScheme.PerUnit, + overagePricing: [], + }; + + const pricePoint: CreateComponentPricePointRequest = { + pricePoint: createComponentPricePointRequestPricePoint, + }; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `promote-component-price-to-default-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + const { component } = await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + await componentPricePointsController.createComponentPricePoint( + component.id || 0, + pricePoint + ); + + const invalidPricePointId = 0; + const invalidComponentId = 0; + + const promoteComponentPricePointToDefaultResponse = + componentPricePointsController.promoteComponentPricePointToDefault( + invalidComponentId, + invalidPricePointId + ); + + expect(promoteComponentPricePointToDefaultResponse).rejects.toThrow(); + + await promoteComponentPricePointToDefaultResponse.catch((reason) => { + expect(reason.statusCode).toBe(404); + }); + }); + it('should not promote component price to default with invalid credentials', async () => { + const newProductPayload: CreateOrUpdateProductRequest = { + product: { + name: `promote-component-price-to-default-name-${uid()}`, + handle: `promote-component-price-to-default-handle-${uid()}`, + description: '', + requireCredit_card: true, + priceInCents: BigInt(1000), + interval: 1, + intervalUnit: IntervalUnit.Month, + }, + }; + + const price: Price = { + starting_quantity: '1', + ending_quantity: '', + unit_price: '1', + startingQuantity: '', + unitPrice: '', + }; + + const productFamilyId = productFamily?.id || 0; + + const createComponentPricePointRequestPricePoint: CreateComponentPricePointRequestPricePoint = + { + name: `price-point-name-${uid()}`, + handle: `price-point-handle-${uid()}`, + prices: [price], + pricing_scheme: 'per_unit', + tax_included: false, + pricingScheme: PricingScheme.PerUnit, + overagePricing: [], + }; + + const pricePoint: CreateComponentPricePointRequest = { + pricePoint: createComponentPricePointRequestPricePoint, + }; + + const meteredComponent: CreateMeteredComponent = { + meteredComponent: { + productFamilyId, + name: `promote-component-price-to-default-component-name${uid()}`, + description: 'test', + quantity: 1, + unitName: 'test', + price: 1, + handle: uid(), + pricingScheme: PricingScheme.PerUnit, + unitPrice: 1, + }, + }; + + const { component } = await prepareDataForComponentResponse( + newProductPayload, + productFamilyId.toString(), + meteredComponent + ); + + await componentPricePointsController.createComponentPricePoint( + component.id || 0, + pricePoint + ); + + const invalidPricePointId = 0; + + const promoteComponentPricePointToDefaultResponse = + invalidComponentPricePointsController.promoteComponentPricePointToDefault( + component.id || 0, + invalidPricePointId + ); + + expect(promoteComponentPricePointToDefaultResponse).rejects.toThrow(); + + await promoteComponentPricePointToDefaultResponse.catch((reason) => { + expect(reason.statusCode).toBe(401); + }); + }); + }); });