1
+ import { expect , use } from 'chai' ;
2
+ import chaiAsPromised from 'chai-as-promised' ;
3
+ import * as sinon from 'sinon' ;
4
+ import sinonChai from 'sinon-chai' ;
5
+ import { testAuth , testUser } from '../../../test/helpers/mock_auth' ;
6
+ import { AuthInternal } from '../../model/auth' ;
7
+ import { User } from '../../model/public_types' ;
8
+ import { AuthMiddlewareQueue } from './middleware' ;
9
+
10
+ use ( chaiAsPromised ) ;
11
+ use ( sinonChai ) ;
12
+
13
+ describe ( 'Auth middleware' , ( ) => {
14
+ let middlewareQueue : AuthMiddlewareQueue ;
15
+ let user : User ;
16
+ let auth : AuthInternal ;
17
+
18
+ beforeEach ( async ( ) => {
19
+ auth = await testAuth ( ) ;
20
+ user = testUser ( auth , 'uid' ) ;
21
+ middlewareQueue = new AuthMiddlewareQueue ( auth ) ;
22
+ } ) ;
23
+
24
+ afterEach ( ( ) => {
25
+ sinon . restore ( ) ;
26
+ } ) ;
27
+
28
+ it ( 'calls middleware in order' , async ( ) => {
29
+ const calls : number [ ] = [ ] ;
30
+
31
+ middlewareQueue . pushCallback ( ( ) => { calls . push ( 1 ) ; } ) ;
32
+ middlewareQueue . pushCallback ( ( ) => { calls . push ( 2 ) ; } ) ;
33
+ middlewareQueue . pushCallback ( ( ) => { calls . push ( 3 ) ; } ) ;
34
+
35
+ await middlewareQueue . runMiddleware ( user ) ;
36
+
37
+ expect ( calls ) . to . eql ( [ 1 , 2 , 3 ] ) ;
38
+ } ) ;
39
+
40
+ it ( 'rejects on error' , async ( ) => {
41
+ middlewareQueue . pushCallback ( ( ) => {
42
+ throw new Error ( 'no' ) ;
43
+ } ) ;
44
+ await expect ( middlewareQueue . runMiddleware ( user ) ) . to . be . rejectedWith ( 'auth/login-blocked' ) ;
45
+ } ) ;
46
+
47
+ it ( 'rejects on promise rejection' , async ( ) => {
48
+ middlewareQueue . pushCallback ( ( ) => Promise . reject ( 'no' ) ) ;
49
+ await expect ( middlewareQueue . runMiddleware ( user ) ) . to . be . rejectedWith ( 'auth/login-blocked' ) ;
50
+ } ) ;
51
+
52
+ it ( 'awaits middleware completion before calling next' , async ( ) => {
53
+ const firstCb = sinon . spy ( ) ;
54
+ const secondCb = sinon . spy ( ) ;
55
+
56
+ middlewareQueue . pushCallback ( ( ) => {
57
+ // Force the first one to run one tick later
58
+ return new Promise ( resolve => {
59
+ setTimeout ( ( ) => {
60
+ firstCb ( ) ;
61
+ resolve ( ) ;
62
+ } , 1 ) ;
63
+ } ) ;
64
+ } ) ;
65
+ middlewareQueue . pushCallback ( secondCb ) ;
66
+
67
+ await middlewareQueue . runMiddleware ( user ) ;
68
+ expect ( secondCb ) . to . have . been . calledAfter ( firstCb ) ;
69
+ } ) ;
70
+
71
+ it ( 'subsequent middleware not run after rejection' , async ( ) => {
72
+ const spy = sinon . spy ( ) ;
73
+
74
+ middlewareQueue . pushCallback ( ( ) => {
75
+ throw new Error ( 'no' ) ;
76
+ } ) ;
77
+ middlewareQueue . pushCallback ( spy ) ;
78
+
79
+ await expect ( middlewareQueue . runMiddleware ( user ) ) . to . be . rejectedWith ( 'auth/login-blocked' ) ;
80
+ expect ( spy ) . not . to . have . been . called ;
81
+ } ) ;
82
+
83
+ it ( 'calls onAbort if provided but only for earlier runs' , async ( ) => {
84
+ const firstOnAbort = sinon . spy ( ) ;
85
+ const secondOnAbort = sinon . spy ( ) ;
86
+
87
+ middlewareQueue . pushCallback ( ( ) => { } , firstOnAbort ) ;
88
+ middlewareQueue . pushCallback ( ( ) => {
89
+ throw new Error ( 'no' ) ;
90
+ } , secondOnAbort ) ;
91
+
92
+ await expect ( middlewareQueue . runMiddleware ( user ) ) . to . be . rejectedWith ( 'auth/login-blocked' ) ;
93
+ expect ( firstOnAbort ) . to . have . been . called ;
94
+ expect ( secondOnAbort ) . not . to . have . been . called ;
95
+ } ) ;
96
+
97
+ it ( 'calls onAbort in order' , async ( ) => {
98
+ const calls : number [ ] = [ ] ;
99
+
100
+ middlewareQueue . pushCallback ( ( ) => { } , ( ) => { calls . push ( 1 ) ; } ) ;
101
+ middlewareQueue . pushCallback ( ( ) => { } , ( ) => { calls . push ( 2 ) ; } ) ;
102
+ middlewareQueue . pushCallback ( ( ) => { } , ( ) => { calls . push ( 3 ) ; } ) ;
103
+ middlewareQueue . pushCallback ( ( ) => {
104
+ throw new Error ( 'no' ) ;
105
+ } ) ;
106
+
107
+ await expect ( middlewareQueue . runMiddleware ( user ) ) . to . be . rejectedWith ( 'auth/login-blocked' ) ;
108
+ expect ( calls ) . to . eql ( [ 3 , 2 , 1 ] ) ;
109
+ } ) ;
110
+
111
+ it ( 'does not call any middleware if user matches null' , async ( ) => {
112
+ const spy = sinon . spy ( ) ;
113
+
114
+ middlewareQueue . pushCallback ( spy ) ;
115
+ await middlewareQueue . runMiddleware ( null ) ;
116
+
117
+ expect ( spy ) . not . to . have . been . called ;
118
+ } ) ;
119
+
120
+ it ( 'does not call any middleware if user matches object' , async ( ) => {
121
+ const spy = sinon . spy ( ) ;
122
+
123
+ // Directly set it manually since the public function creates a
124
+ // copy of the user.
125
+ auth . currentUser = user ;
126
+
127
+ middlewareQueue . pushCallback ( spy ) ;
128
+ await middlewareQueue . runMiddleware ( user ) ;
129
+
130
+ expect ( spy ) . not . to . have . been . called ;
131
+ } ) ;
132
+ } ) ;
0 commit comments