@@ -711,6 +711,217 @@ describe("Cart Update Actions", () => {
711711 ] ) ;
712712 } ) ;
713713
714+ test ( "setLineItemPrice sets an external price for a line item" , async ( ) => {
715+ const product = await supertest ( ctMock . app )
716+ . post ( "/dummy/products" )
717+ . send ( productDraft )
718+ . then ( ( x ) => x . body ) ;
719+
720+ assert ( product , "product not created" ) ;
721+
722+ const baseCartResponse = await supertest ( ctMock . app )
723+ . post ( "/dummy/carts" )
724+ . send ( { currency : "EUR" } ) ;
725+ expect ( baseCartResponse . status ) . toBe ( 201 ) ;
726+ const baseCart = baseCartResponse . body as Cart ;
727+
728+ const addLineItemResponse = await supertest ( ctMock . app )
729+ . post ( `/dummy/carts/${ baseCart . id } ` )
730+ . send ( {
731+ version : baseCart . version ,
732+ actions : [
733+ {
734+ action : "addLineItem" ,
735+ sku : product . masterData . current . masterVariant . sku ,
736+ quantity : 2 ,
737+ key : "line-item-key" ,
738+ } ,
739+ ] ,
740+ } ) ;
741+ expect ( addLineItemResponse . status ) . toBe ( 200 ) ;
742+ const cartWithLineItem = addLineItemResponse . body as Cart ;
743+ const lineItem = cartWithLineItem . lineItems [ 0 ] ;
744+ assert ( lineItem , "lineItem not created" ) ;
745+
746+ const externalPrice : CentPrecisionMoney = {
747+ type : "centPrecision" ,
748+ currencyCode : "EUR" ,
749+ centAmount : 2500 ,
750+ fractionDigits : 2 ,
751+ } ;
752+
753+ const response = await supertest ( ctMock . app )
754+ . post ( `/dummy/carts/${ cartWithLineItem . id } ` )
755+ . send ( {
756+ version : cartWithLineItem . version ,
757+ actions : [
758+ {
759+ action : "setLineItemPrice" ,
760+ lineItemKey : lineItem . key ,
761+ externalPrice,
762+ } ,
763+ ] ,
764+ } ) ;
765+
766+ expect ( response . status ) . toBe ( 200 ) ;
767+ expect ( response . body . version ) . toBe ( cartWithLineItem . version + 1 ) ;
768+ expect ( response . body . lineItems ) . toHaveLength ( 1 ) ;
769+
770+ const updatedLineItem = response . body . lineItems [ 0 ] ;
771+ expect ( updatedLineItem . priceMode ) . toBe ( "ExternalPrice" ) ;
772+ expect ( updatedLineItem . price . value . centAmount ) . toBe (
773+ externalPrice . centAmount ,
774+ ) ;
775+ expect ( updatedLineItem . price . value . currencyCode ) . toBe (
776+ externalPrice . currencyCode ,
777+ ) ;
778+ expect ( updatedLineItem . totalPrice . centAmount ) . toBe (
779+ externalPrice . centAmount * updatedLineItem . quantity ,
780+ ) ;
781+ expect ( response . body . totalPrice . centAmount ) . toBe (
782+ externalPrice . centAmount * updatedLineItem . quantity ,
783+ ) ;
784+ } ) ;
785+
786+ test ( "setLineItemPrice fails when the money uses another currency" , async ( ) => {
787+ const product = await supertest ( ctMock . app )
788+ . post ( "/dummy/products" )
789+ . send ( productDraft )
790+ . then ( ( x ) => x . body ) ;
791+
792+ assert ( product , "product not created" ) ;
793+
794+ const baseCartResponse = await supertest ( ctMock . app )
795+ . post ( "/dummy/carts" )
796+ . send ( { currency : "EUR" } ) ;
797+ expect ( baseCartResponse . status ) . toBe ( 201 ) ;
798+ const baseCart = baseCartResponse . body as Cart ;
799+
800+ const addLineItemResponse = await supertest ( ctMock . app )
801+ . post ( `/dummy/carts/${ baseCart . id } ` )
802+ . send ( {
803+ version : baseCart . version ,
804+ actions : [
805+ {
806+ action : "addLineItem" ,
807+ sku : product . masterData . current . masterVariant . sku ,
808+ quantity : 1 ,
809+ } ,
810+ ] ,
811+ } ) ;
812+ expect ( addLineItemResponse . status ) . toBe ( 200 ) ;
813+ const cartWithLineItem = addLineItemResponse . body as Cart ;
814+ const lineItem = cartWithLineItem . lineItems [ 0 ] ;
815+ assert ( lineItem , "lineItem not created" ) ;
816+
817+ const response = await supertest ( ctMock . app )
818+ . post ( `/dummy/carts/${ cartWithLineItem . id } ` )
819+ . send ( {
820+ version : cartWithLineItem . version ,
821+ actions : [
822+ {
823+ action : "setLineItemPrice" ,
824+ lineItemId : lineItem . id ,
825+ externalPrice : {
826+ type : "centPrecision" ,
827+ currencyCode : "USD" ,
828+ centAmount : 5000 ,
829+ fractionDigits : 2 ,
830+ } ,
831+ } ,
832+ ] ,
833+ } ) ;
834+
835+ expect ( response . status ) . toBe ( 400 ) ;
836+ expect ( response . body . message ) . toContain ( "Currency mismatch" ) ;
837+ } ) ;
838+
839+ test ( "setLineItemPrice removes external price when no value is provided" , async ( ) => {
840+ const product = await supertest ( ctMock . app )
841+ . post ( "/dummy/products" )
842+ . send ( productDraft )
843+ . then ( ( x ) => x . body ) ;
844+
845+ assert ( product , "product not created" ) ;
846+
847+ const baseCartResponse = await supertest ( ctMock . app )
848+ . post ( "/dummy/carts" )
849+ . send ( { currency : "EUR" } ) ;
850+ expect ( baseCartResponse . status ) . toBe ( 201 ) ;
851+ const baseCart = baseCartResponse . body as Cart ;
852+
853+ const addLineItemResponse = await supertest ( ctMock . app )
854+ . post ( `/dummy/carts/${ baseCart . id } ` )
855+ . send ( {
856+ version : baseCart . version ,
857+ actions : [
858+ {
859+ action : "addLineItem" ,
860+ sku : product . masterData . current . masterVariant . sku ,
861+ quantity : 1 ,
862+ } ,
863+ ] ,
864+ } ) ;
865+ expect ( addLineItemResponse . status ) . toBe ( 200 ) ;
866+ const cartWithLineItem = addLineItemResponse . body as Cart ;
867+ const lineItem = cartWithLineItem . lineItems [ 0 ] ;
868+ assert ( lineItem , "lineItem not created" ) ;
869+
870+ const externalPrice : CentPrecisionMoney = {
871+ type : "centPrecision" ,
872+ currencyCode : "EUR" ,
873+ centAmount : 1000 ,
874+ fractionDigits : 2 ,
875+ } ;
876+
877+ const setExternalPriceResponse = await supertest ( ctMock . app )
878+ . post ( `/dummy/carts/${ cartWithLineItem . id } ` )
879+ . send ( {
880+ version : cartWithLineItem . version ,
881+ actions : [
882+ {
883+ action : "setLineItemPrice" ,
884+ lineItemId : lineItem . id ,
885+ externalPrice,
886+ } ,
887+ ] ,
888+ } ) ;
889+ expect ( setExternalPriceResponse . status ) . toBe ( 200 ) ;
890+ const cartWithExternalPrice = setExternalPriceResponse . body as Cart ;
891+ expect ( cartWithExternalPrice . lineItems [ 0 ] . priceMode ) . toBe ( "ExternalPrice" ) ;
892+
893+ const resetResponse = await supertest ( ctMock . app )
894+ . post ( `/dummy/carts/${ cartWithExternalPrice . id } ` )
895+ . send ( {
896+ version : cartWithExternalPrice . version ,
897+ actions : [
898+ {
899+ action : "setLineItemPrice" ,
900+ lineItemId : lineItem . id ,
901+ } ,
902+ ] ,
903+ } ) ;
904+
905+ expect ( resetResponse . status ) . toBe ( 200 ) ;
906+ expect ( resetResponse . body . version ) . toBe ( cartWithExternalPrice . version + 1 ) ;
907+ expect ( resetResponse . body . lineItems ) . toHaveLength ( 1 ) ;
908+
909+ const revertedLineItem = resetResponse . body . lineItems [ 0 ] ;
910+ const expectedCentAmount =
911+ product . masterData . current . masterVariant . prices ?. [ 0 ] . value . centAmount ;
912+ if ( typeof expectedCentAmount !== "number" ) {
913+ throw new Error ( "product price not found" ) ;
914+ }
915+ expect ( revertedLineItem . priceMode ) . toBe ( "Platform" ) ;
916+ expect ( revertedLineItem . price . value . centAmount ) . toBe ( expectedCentAmount ) ;
917+ expect ( revertedLineItem . totalPrice . centAmount ) . toBe (
918+ expectedCentAmount * revertedLineItem . quantity ,
919+ ) ;
920+ expect ( resetResponse . body . totalPrice . centAmount ) . toBe (
921+ expectedCentAmount * revertedLineItem . quantity ,
922+ ) ;
923+ } ) ;
924+
714925 test ( "setLineItemCustomField" , async ( ) => {
715926 const product = await supertest ( ctMock . app )
716927 . post ( "/dummy/products" )
0 commit comments