1
+ /**
2
+ * @license
3
+ * Copyright 2020 Google LLC.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ import { expect , use } from 'chai' ;
19
+ import * as sinon from 'sinon' ;
20
+ import * as sinonChai from 'sinon-chai' ;
21
+
22
+ import { FirebaseError } from '@firebase/util' ;
23
+
24
+ import { _open , _uaGetter , AuthPopup } from './popup' ;
25
+
26
+ use ( sinonChai ) ;
27
+
28
+ describe ( 'src/core/util/popup' , ( ) => {
29
+ let windowOpenStub : sinon . SinonStub ;
30
+ let popupStub : sinon . SinonStubbedInstance < Window > ;
31
+
32
+ function setUA ( ua : string ) : void {
33
+ sinon . stub ( _uaGetter , 'getUA' ) . returns ( ua ) ;
34
+ }
35
+
36
+ function windowTarget ( ) : string {
37
+ return windowOpenStub . firstCall . args [ 1 ] ;
38
+ }
39
+
40
+ function windowURL ( ) : string {
41
+ return windowOpenStub . firstCall . args [ 0 ] ;
42
+ }
43
+
44
+ function windowOptions ( ) : string {
45
+ return windowOpenStub . firstCall . args [ 2 ] ;
46
+ }
47
+
48
+ beforeEach ( ( ) => {
49
+ windowOpenStub = sinon . stub ( window , 'open' ) ;
50
+ popupStub = sinon . stub ( {
51
+ focus : ( ) => { } ,
52
+ close : ( ) => { } ,
53
+ } as unknown as Window ) ;
54
+ windowOpenStub . returns ( popupStub ) ;
55
+ } ) ;
56
+
57
+ afterEach ( ( ) => {
58
+ sinon . restore ( ) ;
59
+ } ) ;
60
+
61
+ it ( 'sets target to name param if not chrome UA' , ( ) => {
62
+ setUA ( 'notchrome' ) ;
63
+ _open ( 'appName' , 'url' , 'name' ) ;
64
+ expect ( windowTarget ( ) ) . to . eq ( 'name' ) ;
65
+ } ) ;
66
+
67
+ it ( 'sets target to _blank if on chrome IOS' , ( ) => {
68
+ setUA ( 'crios/' ) ;
69
+ _open ( 'appName' , 'url' , 'name' ) ;
70
+ expect ( windowTarget ( ) ) . to . eq ( '_blank' ) ;
71
+ } ) ;
72
+
73
+ it ( 'sets the firefox url to a default if not provided' , ( ) => {
74
+ setUA ( 'firefox/' ) ;
75
+ _open ( 'appName' ) ;
76
+ expect ( windowURL ( ) ) . to . eq ( 'http://localhost' ) ;
77
+ } ) ;
78
+
79
+ it ( 'sets the firefox url to the value provided' , ( ) => {
80
+ setUA ( 'firefox/' ) ;
81
+ _open ( 'appName' , 'url' ) ;
82
+ expect ( windowURL ( ) ) . to . eq ( 'url' ) ;
83
+ } ) ;
84
+
85
+ it ( 'sets non-firefox url to empty if not provided' , ( ) => {
86
+ setUA ( 'not-ff/' ) ;
87
+ _open ( 'appName' ) ;
88
+ expect ( windowURL ( ) ) . to . eq ( '' ) ;
89
+ } ) ;
90
+
91
+ it ( 'sets non-firefox url to url if not provided' , ( ) => {
92
+ setUA ( 'not-ff/' ) ;
93
+ _open ( 'appName' , 'url' ) ;
94
+ expect ( windowURL ( ) ) . to . eq ( 'url' ) ;
95
+ } ) ;
96
+
97
+ it ( 'sets scrollbars to yes in popup' , ( ) => {
98
+ setUA ( 'firefox/' ) ;
99
+ _open ( 'appName' ) ;
100
+ expect ( windowOptions ( ) ) . to . include ( 'scrollbars=yes' ) ;
101
+ } ) ;
102
+
103
+ it ( 'errors if the popup is blocked' , ( ) => {
104
+ setUA ( '' ) ;
105
+ windowOpenStub . returns ( undefined ) ;
106
+ expect ( ( ) => _open ( 'appName' ) ) . to . throw ( FirebaseError , 'auth/popup-blocked' ) ;
107
+ } ) ;
108
+
109
+ it ( 'builds the proper options string' , ( ) => {
110
+ const screen = window . screen ;
111
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
112
+ ( window as any ) . sreen = {
113
+ availHeight : 1000 ,
114
+ availWidth : 2000 ,
115
+ } ;
116
+
117
+ setUA ( '' ) ;
118
+ _open ( 'appName' ) ;
119
+ const options = windowOptions ( ) . split ( ',' ) . filter ( s => ! ! s ) . map ( prop => prop . split ( '=' ) )
120
+ . reduce < Record < string , string > > ( ( accum , [ prop , val ] ) => {
121
+ accum [ prop ] = val ;
122
+ return accum ;
123
+ } , { } ) ;
124
+
125
+ expect ( options ) . to . eql ( {
126
+ location : 'yes' ,
127
+ resizable : 'yes' ,
128
+ statusbar : 'yes' ,
129
+ toolbar : 'no' ,
130
+ width : '500' ,
131
+ height : '600' ,
132
+ top : '0' ,
133
+ left : '0' ,
134
+ } ) ;
135
+
136
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
137
+ ( window as any ) . screen = screen ;
138
+ } ) ;
139
+
140
+ it ( 'calls focus on the new popup' , ( ) => {
141
+ setUA ( '' ) ;
142
+ _open ( 'appName' ) ;
143
+ expect ( popupStub . focus ) . to . have . been . called ;
144
+ } ) ;
145
+
146
+ it ( 'does not fail if window.focus errors' , ( ) => {
147
+ popupStub . focus . throws ( new Error ( 'lol no' ) ) ;
148
+ setUA ( '' ) ;
149
+ expect ( ( ) => _open ( 'appName' ) ) . not . to . throw ( Error ) ;
150
+ } ) ;
151
+
152
+ context ( 'resulting popup object' , ( ) => {
153
+ let authPopup : AuthPopup ;
154
+ beforeEach ( ( ) => {
155
+ setUA ( '' ) ;
156
+ authPopup = _open ( 'appName' ) ;
157
+ } ) ;
158
+
159
+ it ( 'has a window object' , ( ) => {
160
+ expect ( authPopup . window ) . to . eq ( popupStub ) ;
161
+ } ) ;
162
+
163
+ it ( 'calls through to the popup close' , ( ) => {
164
+ authPopup . close ( ) ;
165
+ expect ( popupStub . close ) . to . have . been . called ;
166
+ } ) ;
167
+
168
+ it ( 'close() does not error if underlying call errors' , ( ) => {
169
+ popupStub . close . throws ( new Error ( 'not this time' ) ) ;
170
+ expect ( ( ) => authPopup . close ( ) ) . not . to . throw ( Error ) ;
171
+ } ) ;
172
+ } ) ;
173
+ } ) ;
0 commit comments