55const { mount, config } = require ( "@vue/test-utils" ) ;
66const VueNextRx = require ( "../dist/rx-vue-next.js" ) ;
77const { Observable } = require ( "rxjs" ) ;
8- const { startWith } = require ( "rxjs/operators" ) ;
8+ const {
9+ startWith,
10+ map,
11+ tap,
12+ scan,
13+ merge,
14+ filter,
15+ pluck,
16+ } = require ( "rxjs/operators" ) ;
917
1018config . global . plugins . push ( VueNextRx ) ;
1119
1220const defaultTemplate = "<div id='test'>Hello world</div>" ;
21+ const varTemplate = ( val ) => `<div id='test'>{{${ val } }}</div>` ;
1322
1423function mock ( ) {
1524 let observer ;
@@ -22,7 +31,17 @@ function mock() {
2231 } ;
2332}
2433
25- test ( "Subscriptions Basic" , ( ) => {
34+ function trigger ( target , event ) {
35+ var e = document . createEvent ( "HTMLEvents" ) ;
36+ e . initEvent ( event , true , true ) ;
37+ target . dispatchEvent ( e ) ;
38+ }
39+
40+ function click ( target ) {
41+ trigger ( target , "click" ) ;
42+ }
43+
44+ test ( "Expose observable" , ( ) => {
2645 const { ob, next } = mock ( ) ;
2746 const component = {
2847 template : defaultTemplate ,
@@ -44,3 +63,265 @@ test("Subscriptions Basic", () => {
4463 // Assert the rendered text of the component
4564 expect ( wrapper . text ( ) ) . toContain ( "Hello world" ) ;
4665} ) ;
66+
67+ test ( "Bind subscriptions to render" , ( done ) => {
68+ const { ob, next } = mock ( ) ;
69+ const component = {
70+ template : varTemplate ( "hello" ) ,
71+ subscriptions ( ) {
72+ return { hello : ob . pipe ( startWith ( "foo" ) ) } ;
73+ } ,
74+ } ;
75+ const wrapper = mount ( component ) ;
76+
77+ expect ( wrapper . text ( ) ) . toBe ( "foo" ) ;
78+
79+ next ( "bar" ) ;
80+ wrapper . componentVM . $nextTick ( ( ) => {
81+ expect ( wrapper . text ( ) ) . toBe ( "bar" ) ;
82+ } ) ;
83+ done ( ) ;
84+ } ) ;
85+
86+ test ( "subscriptions() has access to component inject" , ( ) => {
87+ const { ob } = mock ( ) ;
88+
89+ const component = {
90+ template : varTemplate ( "hello" ) ,
91+ data ( ) {
92+ return { foo : "FOO" } ;
93+ } ,
94+ inject : { bar : { default : "BAR" } } ,
95+ subscriptions ( ) {
96+ return {
97+ hello : ob . pipe ( startWith ( this . foo + this . bar ) ) ,
98+ } ;
99+ } ,
100+ } ;
101+
102+ const wrapper = mount ( component ) ;
103+
104+ expect ( wrapper . text ( ) ) . toBe ( "FOOBAR" ) ;
105+ } ) ;
106+
107+ test ( "subscriptions() can throw error properly" , ( done ) => {
108+ const { ob, next } = mock ( ) ;
109+ let thrownError ;
110+
111+ const component = {
112+ template : varTemplate ( "num" ) ,
113+ subscriptions ( ) {
114+ return {
115+ num : ob . pipe (
116+ startWith ( 1 ) ,
117+ map ( ( n ) => n . toFixed ( ) ) ,
118+ tap ( {
119+ error ( err ) {
120+ thrownError = err ;
121+ } ,
122+ } )
123+ ) ,
124+ } ;
125+ } ,
126+ } ;
127+
128+ const wrapper = mount ( component ) ;
129+
130+ wrapper . componentVM . $nextTick ( ( ) => {
131+ next ( null ) ;
132+
133+ wrapper . componentVM . $nextTick ( ( ) => {
134+ expect ( thrownError ) . toBeDefined ( ) ;
135+ expect ( wrapper . text ( ) ) . toBe ( "1" ) ;
136+ done ( ) ;
137+ } ) ;
138+ } ) ;
139+ } ) ;
140+
141+ test ( "v-stream directive (basic)" , ( done ) => {
142+ const component = {
143+ template : `
144+ <div>
145+ <span class="count">{{ count }}</span>
146+ <button v-stream:click="click$">+</button>
147+ </div>
148+ ` ,
149+ domStreams : [ "click$" ] ,
150+ subscriptions ( ) {
151+ return {
152+ count : this . click$ . pipe (
153+ map ( ( ) => 1 ) ,
154+ startWith ( 0 ) ,
155+ scan ( ( total , change ) => total + change )
156+ ) ,
157+ } ;
158+ } ,
159+ } ;
160+
161+ const wrapper = mount ( component ) ;
162+
163+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "0" ) ;
164+ click ( wrapper . element . querySelector ( "button" ) ) ;
165+ wrapper . componentVM . $nextTick ( ( ) => {
166+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "1" ) ;
167+ done ( ) ;
168+ } ) ;
169+ } ) ;
170+
171+ test ( "v-stream directive (with .native modify)" , ( done ) => {
172+ const component = {
173+ template : `
174+ <div>
175+ <span class="count">{{ count }}</span>
176+ <my-button id="btn-native" v-stream:click.native="clickNative$">+</my-button>
177+ <my-button id="btn" v-stream:click="click$">-</my-button>
178+ </div>
179+ ` ,
180+ components : {
181+ myButton : {
182+ template : "<button>MyButton</button>" ,
183+ } ,
184+ } ,
185+ domStreams : [ "clickNative$" , "click$" ] ,
186+ subscriptions ( ) {
187+ return {
188+ count : this . clickNative$ . pipe (
189+ merge ( this . click$ ) ,
190+ filter ( ( e ) => e . event . target && e . event . target . id === "btn-native" ) ,
191+ map ( ( ) => 1 ) ,
192+ startWith ( 0 ) ,
193+ scan ( ( total , change ) => total + change )
194+ ) ,
195+ } ;
196+ } ,
197+ } ;
198+
199+ const wrapper = mount ( component ) ;
200+
201+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "0" ) ;
202+ click ( wrapper . element . querySelector ( "#btn" ) ) ;
203+ click ( wrapper . element . querySelector ( "#btn" ) ) ;
204+ click ( wrapper . element . querySelector ( "#btn-native" ) ) ;
205+ wrapper . componentVM . $nextTick ( ( ) => {
206+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "1" ) ;
207+ done ( ) ;
208+ } ) ;
209+ } ) ;
210+
211+ test ( "v-stream directive (with .stop, .prevent modify)" , ( done ) => {
212+ const component = {
213+ template : `
214+ <form>
215+ <span>{{stoped}} {{prevented}}</span>
216+ <button id="btn-stop" v-stream:click.stop="clickStop$">Stop</button>
217+ <button id="btn-prevent" type="submit" v-stream:click.prevent="clickPrevent$">Submit</button>
218+ </form>
219+ ` ,
220+ domStreams : [ "clickStop$" , "clickPrevent$" ] ,
221+ subscriptions ( ) {
222+ return {
223+ stoped : this . clickStop$ . pipe ( map ( ( x ) => x . event . cancelBubble ) ) ,
224+ prevented : this . clickPrevent$ . pipe (
225+ map ( ( x ) => x . event . defaultPrevented )
226+ ) ,
227+ } ;
228+ } ,
229+ } ;
230+
231+ const wrapper = mount ( component ) ;
232+
233+ click ( wrapper . element . querySelector ( "#btn-stop" ) ) ;
234+ click ( wrapper . element . querySelector ( "#btn-prevent" ) ) ;
235+ wrapper . componentVM . $nextTick ( ( ) => {
236+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "true true" ) ;
237+ done ( ) ;
238+ } ) ;
239+ } ) ;
240+
241+ test ( "v-stream directive (multiple bindings on same node)" , ( done ) => {
242+ const component = {
243+ template : `
244+ <div>
245+ <span class="count">{{ count }}</span>
246+ <button
247+ v-stream:click="{ subject: plus$, data: 1 }"
248+ v-stream:keyup="{ subject: plus$, data: -1 }">+</button>
249+ </div>
250+ ` ,
251+ domStreams : [ "plus$" ] ,
252+ subscriptions ( ) {
253+ return {
254+ count : this . plus$ . pipe (
255+ pluck ( "data" ) ,
256+ startWith ( 0 ) ,
257+ scan ( ( total , change ) => total + change )
258+ ) ,
259+ } ;
260+ } ,
261+ } ;
262+
263+ const wrapper = mount ( component ) ;
264+
265+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "0" ) ;
266+ click ( wrapper . element . querySelector ( "button" ) ) ;
267+ wrapper . componentVM . $nextTick ( ( ) => {
268+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "1" ) ;
269+ trigger ( wrapper . element . querySelector ( "button" ) , "keyup" ) ;
270+ wrapper . componentVM . $nextTick ( ( ) => {
271+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "0" ) ;
272+ done ( ) ;
273+ } ) ;
274+ } ) ;
275+ } ) ;
276+
277+ test ( "$fromDOMEvent()" , ( done ) => {
278+ const component = {
279+ template : `
280+ <div>
281+ <span class="count">{{ count }}</span>
282+ <button>+</button>
283+ </div>
284+ ` ,
285+ subscriptions ( ) {
286+ const click$ = this . $fromDOMEvent ( "button" , "click" ) ;
287+ return {
288+ count : click$ . pipe (
289+ map ( ( ) => 1 ) ,
290+ startWith ( 0 ) ,
291+ scan ( ( total , change ) => total + change )
292+ ) ,
293+ } ;
294+ } ,
295+ } ;
296+ const wrapper = mount ( component ) ;
297+
298+ document . body . appendChild ( wrapper . element ) ;
299+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "0" ) ;
300+ click ( wrapper . element . querySelector ( "button" ) ) ;
301+ wrapper . componentVM . $nextTick ( ( ) => {
302+ expect ( wrapper . element . querySelector ( "span" ) . textContent ) . toBe ( "1" ) ;
303+ done ( ) ;
304+ } ) ;
305+ } ) ;
306+
307+ test ( "$subscribeTo()" , ( ) => {
308+ const { ob, next } = mock ( ) ;
309+ const results = [ ] ;
310+ const component = {
311+ template : defaultTemplate ,
312+ created ( ) {
313+ this . $subscribeTo ( ob , ( count ) => {
314+ results . push ( count ) ;
315+ } ) ;
316+ } ,
317+ } ;
318+
319+ const wrapper = mount ( component ) ;
320+
321+ next ( 1 ) ;
322+ expect ( results ) . toEqual ( [ 1 ] ) ;
323+
324+ wrapper . unmount ( ) ;
325+ next ( 2 ) ;
326+ expect ( results ) . toEqual ( [ 1 ] ) ; // should not trigger anymore
327+ } ) ;
0 commit comments