@@ -2,7 +2,7 @@ import { expect } from 'chai';
22import * as sinon from 'sinon' ;
33import { Observer , TeardownLogic } from '../src/internal/types' ;
44import { Observable , config , Subscription , noop , Subscriber , Operator , NEVER , Subject , of , throwError , empty } from 'rxjs' ;
5- import { map , multicast , refCount , filter , count , tap , combineLatest , concat , merge , race , zip , catchError , concatMap , switchMap } from 'rxjs/operators' ;
5+ import { map , multicast , refCount , filter , count , tap , combineLatest , concat , merge , race , zip , catchError , concatMap , switchMap , publish , publishLast , publishBehavior , share } from 'rxjs/operators' ;
66import { TestScheduler } from 'rxjs/testing' ;
77import { observableMatcher } from './helpers/observableMatcher' ;
88
@@ -810,6 +810,246 @@ describe('Observable.lift', () => {
810810 ) ;
811811 } ) ;
812812
813+
814+ it ( 'should compose through publish and refCount' , ( done ) => {
815+ const result = new MyCustomObservable < number > ( ( observer ) => {
816+ observer . next ( 1 ) ;
817+ observer . next ( 2 ) ;
818+ observer . next ( 3 ) ;
819+ observer . complete ( ) ;
820+ } ) . pipe (
821+ publish ( ) ,
822+ refCount ( ) ,
823+ map ( ( x ) => 10 * x )
824+ ) ;
825+
826+ expect ( result instanceof MyCustomObservable ) . to . be . true ;
827+
828+ const expected = [ 10 , 20 , 30 ] ;
829+
830+ result . subscribe (
831+ function ( x ) {
832+ expect ( x ) . to . equal ( expected . shift ( ) ) ;
833+ } ,
834+ ( ) => {
835+ done ( new Error ( 'should not be called' ) ) ;
836+ } ,
837+ ( ) => {
838+ done ( ) ;
839+ }
840+ ) ;
841+ } ) ;
842+
843+
844+ it ( 'should compose through publishLast and refCount' , ( done ) => {
845+ const result = new MyCustomObservable < number > ( ( observer ) => {
846+ observer . next ( 1 ) ;
847+ observer . next ( 2 ) ;
848+ observer . next ( 3 ) ;
849+ observer . complete ( ) ;
850+ } ) . pipe (
851+ publishLast ( ) ,
852+ refCount ( ) ,
853+ map ( ( x ) => 10 * x )
854+ ) ;
855+
856+ expect ( result instanceof MyCustomObservable ) . to . be . true ;
857+
858+ const expected = [ 30 ] ;
859+
860+ result . subscribe (
861+ function ( x ) {
862+ expect ( x ) . to . equal ( expected . shift ( ) ) ;
863+ } ,
864+ ( ) => {
865+ done ( new Error ( 'should not be called' ) ) ;
866+ } ,
867+ ( ) => {
868+ done ( ) ;
869+ }
870+ ) ;
871+ } ) ;
872+
873+ it ( 'should compose through publishBehavior and refCount' , ( done ) => {
874+ const result = new MyCustomObservable < number > ( ( observer ) => {
875+ observer . next ( 1 ) ;
876+ observer . next ( 2 ) ;
877+ observer . next ( 3 ) ;
878+ observer . complete ( ) ;
879+ } ) . pipe (
880+ publishBehavior ( 0 ) ,
881+ refCount ( ) ,
882+ map ( ( x ) => 10 * x )
883+ ) ;
884+
885+ expect ( result instanceof MyCustomObservable ) . to . be . true ;
886+
887+ const expected = [ 0 , 10 , 20 , 30 ] ;
888+
889+ result . subscribe (
890+ function ( x ) {
891+ expect ( x ) . to . equal ( expected . shift ( ) ) ;
892+ } ,
893+ ( ) => {
894+ done ( new Error ( 'should not be called' ) ) ;
895+ } ,
896+ ( ) => {
897+ done ( ) ;
898+ }
899+ ) ;
900+ } ) ;
901+
902+ it ( 'should composes Subjects in the simple case' , ( ) => {
903+ const subject = new Subject < number > ( ) ;
904+
905+ const result = subject . pipe (
906+ map ( ( x ) => 10 * x )
907+ ) as any as Subject < number > ; // Yes, this is correct. (but you're advised not to do this)
908+
909+ expect ( result instanceof Subject ) . to . be . true ;
910+
911+ const emitted : any [ ] = [ ] ;
912+ result . subscribe ( value => emitted . push ( value ) ) ;
913+
914+ result . next ( 10 ) ;
915+ result . next ( 20 ) ;
916+ result . next ( 30 ) ;
917+
918+ expect ( emitted ) . to . deep . equal ( [ 100 , 200 , 300 ] ) ;
919+ } ) ;
920+
921+ /**
922+ * Seriously, never do this. It's probably bad that we've allowed this. Fortunately, it's not
923+ * a common practice, so maybe we can remove it?
924+ */
925+ it ( 'should demonstrate the horrors of sharing and lifting the Subject through' , ( ) => {
926+ const subject = new Subject < number > ( ) ;
927+
928+ const shared = subject . pipe (
929+ share ( )
930+ ) ;
931+
932+ const result1 = shared . pipe (
933+ map ( x => x * 10 )
934+ ) as any as Subject < number > ; // Yes, this is correct.
935+
936+ const result2 = shared . pipe (
937+ map ( x => x - 10 )
938+ ) as any as Subject < number > ; // Yes, this is correct.
939+ expect ( result1 instanceof Subject ) . to . be . true ;
940+
941+ const emitted1 : any [ ] = [ ] ;
942+ result1 . subscribe ( value => emitted1 . push ( value ) ) ;
943+
944+ const emitted2 : any [ ] = [ ] ;
945+ result2 . subscribe ( value => emitted2 . push ( value ) ) ;
946+
947+ // THIS IS HORRIBLE DON'T DO THIS.
948+ result1 . next ( 10 ) ;
949+ result2 . next ( 20 ) ; // Yuck
950+ result1 . next ( 30 ) ;
951+
952+ expect ( emitted1 ) . to . deep . equal ( [ 100 , 200 , 300 ] ) ;
953+ expect ( emitted2 ) . to . deep . equal ( [ 0 , 10 , 20 ] ) ;
954+ } ) ;
955+
956+ /**
957+ * This section outlines one of the reasons that we need to get rid of operators that return
958+ * Connectable observable. Likewise it also reveals a slight design flaw in `lift`. It
959+ * probably should have never tried to compose through the Subject's observer methods.
960+ * If you're a user and you're reading this... NEVER try to use this feature, it's likely
961+ * to go away at some point.
962+ *
963+ * The problem is that you can have the Subject parts, or you can have the ConnectableObservable parts,
964+ * but you can't have both.
965+ */
966+ describe . skip ( 'The lift through Connectable gaff' , ( ) => {
967+ it ( 'should compose through multicast and refCount, even if it is a Subject' , ( ) => {
968+ const subject = new Subject < number > ( ) ;
969+
970+ const result = subject . pipe (
971+ multicast ( ( ) => new Subject < number > ( ) ) ,
972+ refCount ( ) ,
973+ map ( ( x ) => 10 * x )
974+ ) as any as Subject < number > ; // Yes, this is correct.
975+
976+ expect ( result instanceof Subject ) . to . be . true ;
977+
978+ const emitted : any [ ] = [ ] ;
979+ result . subscribe ( value => emitted . push ( value ) ) ;
980+
981+ result . next ( 10 ) ;
982+ result . next ( 20 ) ;
983+ result . next ( 30 ) ;
984+
985+ expect ( emitted ) . to . deep . equal ( [ 100 , 200 , 300 ] ) ;
986+ } ) ;
987+
988+ it ( 'should compose through publish and refCount, even if it is a Subject' , ( ) => {
989+ const subject = new Subject < number > ( ) ;
990+
991+ const result = subject . pipe (
992+ publish ( ) ,
993+ refCount ( ) ,
994+ map ( ( x ) => 10 * x )
995+ ) as any as Subject < number > ; // Yes, this is correct.
996+
997+ expect ( result instanceof Subject ) . to . be . true ;
998+
999+ const emitted : any [ ] = [ ] ;
1000+ result . subscribe ( value => emitted . push ( value ) ) ;
1001+
1002+ result . next ( 10 ) ;
1003+ result . next ( 20 ) ;
1004+ result . next ( 30 ) ;
1005+
1006+ expect ( emitted ) . to . deep . equal ( [ 100 , 200 , 300 ] ) ;
1007+ } ) ;
1008+
1009+
1010+ it ( 'should compose through publishLast and refCount, even if it is a Subject' , ( ) => {
1011+ const subject = new Subject < number > ( ) ;
1012+
1013+ const result = subject . pipe (
1014+ publishLast ( ) ,
1015+ refCount ( ) ,
1016+ map ( ( x ) => 10 * x )
1017+ ) as any as Subject < number > ; // Yes, this is correct.
1018+
1019+ expect ( result instanceof Subject ) . to . be . true ;
1020+
1021+ const emitted : any [ ] = [ ] ;
1022+ result . subscribe ( value => emitted . push ( value ) ) ;
1023+
1024+ result . next ( 10 ) ;
1025+ result . next ( 20 ) ;
1026+ result . next ( 30 ) ;
1027+
1028+ expect ( emitted ) . to . deep . equal ( [ 100 , 200 , 300 ] ) ;
1029+ } ) ;
1030+
1031+ it ( 'should compose through publishBehavior and refCount, even if it is a Subject' , ( ) => {
1032+ const subject = new Subject < number > ( ) ;
1033+
1034+ const result = subject . pipe (
1035+ publishBehavior ( 0 ) ,
1036+ refCount ( ) ,
1037+ map ( ( x ) => 10 * x )
1038+ ) as any as Subject < number > ; // Yes, this is correct.
1039+
1040+ expect ( result instanceof Subject ) . to . be . true ;
1041+
1042+ const emitted : any [ ] = [ ] ;
1043+ result . subscribe ( value => emitted . push ( value ) ) ;
1044+
1045+ result . next ( 10 ) ;
1046+ result . next ( 20 ) ;
1047+ result . next ( 30 ) ;
1048+
1049+ expect ( emitted ) . to . deep . equal ( [ 0 , 100 , 200 , 300 ] ) ;
1050+ } ) ;
1051+ } ) ;
1052+
8131053 it ( 'should compose through multicast with selector function' , ( done ) => {
8141054 const result = new MyCustomObservable < number > ( ( observer ) => {
8151055 observer . next ( 1 ) ;
0 commit comments