Skip to content

Commit f2562c2

Browse files
authored
Add the warning banner / console message to TS Auth SDK (#4119)
* Add emulator banner to typescript SDK * Formatting * Formatting * Make the api conform to specifications * Formatting
1 parent 09c537d commit f2562c2

File tree

4 files changed

+91
-4
lines changed

4 files changed

+91
-4
lines changed

packages-exp/auth-compat-exp/src/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ export class Auth
9797
signOut(): Promise<void> {
9898
return this.auth.signOut();
9999
}
100-
useEmulator(url: string): void {
101-
this.auth.useEmulator(url);
100+
useEmulator(url: string, options?: { disableWarnings: boolean }): void {
101+
this.auth.useEmulator(url, options);
102102
}
103103
applyActionCode(code: string): Promise<void> {
104104
return impl.applyActionCode(this.auth, code);

packages-exp/auth-exp/src/core/auth/auth_impl.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,16 @@ describe('core/auth/auth_impl useEmulator', () => {
486486

487487
afterEach(() => {
488488
fetch.tearDown();
489+
sinon.restore();
490+
491+
// The DOM persists through tests; remove the banner if it is attached
492+
const banner =
493+
typeof document !== 'undefined'
494+
? document.querySelector('.firebase-emulator-warning')
495+
: null;
496+
if (banner) {
497+
banner.parentElement?.removeChild(banner);
498+
}
489499
});
490500

491501
context('useEmulator', () => {
@@ -519,6 +529,41 @@ describe('core/auth/auth_impl useEmulator', () => {
519529
'auth/invalid-emulator-scheme'
520530
);
521531
});
532+
533+
it('attaches a banner to the DOM', () => {
534+
auth.useEmulator('http://localhost:2020');
535+
if (typeof document !== 'undefined') {
536+
const el = document.querySelector('.firebase-emulator-warning')!;
537+
expect(el).not.to.be.null;
538+
expect(el.textContent).to.eq(
539+
'Running in emulator mode. ' +
540+
'Do not use with production credentials.'
541+
);
542+
}
543+
});
544+
545+
it('logs out a warning to the console', () => {
546+
sinon.stub(console, 'info');
547+
auth.useEmulator('http://localhost:2020');
548+
expect(console.info).to.have.been.calledWith(
549+
'WARNING: You are using the Auth Emulator,' +
550+
' which is intended for local testing only. Do not use with' +
551+
' production credentials.'
552+
);
553+
});
554+
555+
it('logs out the warning but has no banner if disableBanner true', () => {
556+
sinon.stub(console, 'info');
557+
auth.useEmulator('http://localhost:2020', { disableWarnings: true });
558+
expect(console.info).to.have.been.calledWith(
559+
'WARNING: You are using the Auth Emulator,' +
560+
' which is intended for local testing only. Do not use with' +
561+
' production credentials.'
562+
);
563+
if (typeof document !== 'undefined') {
564+
expect(document.querySelector('.firebase-emulator-warning')).to.be.null;
565+
}
566+
});
522567
});
523568

524569
context('toJSON', () => {

packages-exp/auth-exp/src/core/auth/auth_impl.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export class AuthImpl implements Auth, _FirebaseService {
271271
this.languageCode = _getUserLanguage();
272272
}
273273

274-
useEmulator(url: string): void {
274+
useEmulator(url: string, options?: { disableWarnings: boolean }): void {
275275
_assert(this._canInitEmulator, this, AuthErrorCode.EMULATOR_CONFIG_FAILED);
276276

277277
_assert(
@@ -282,6 +282,7 @@ export class AuthImpl implements Auth, _FirebaseService {
282282

283283
this.config.emulator = { url };
284284
this.settings.appVerificationDisabledForTesting = true;
285+
emitEmulatorWarning(!!options?.disableWarnings);
285286
}
286287

287288
async _delete(): Promise<void> {
@@ -567,3 +568,43 @@ class Subscription<T> {
567568
return this.observer.next.bind(this.observer);
568569
}
569570
}
571+
572+
function emitEmulatorWarning(disableBanner: boolean): void {
573+
function attachBanner(): void {
574+
const el = document.createElement('p');
575+
const sty = el.style;
576+
el.innerText =
577+
'Running in emulator mode. Do not use with production credentials.';
578+
sty.position = 'fixed';
579+
sty.width = '100%';
580+
sty.backgroundColor = '#ffffff';
581+
sty.border = '.1em solid #000000';
582+
sty.color = '#ff0000';
583+
sty.bottom = '0px';
584+
sty.left = '0px';
585+
sty.margin = '0px';
586+
sty.zIndex = '10000';
587+
sty.textAlign = 'center';
588+
el.classList.add('firebase-emulator-warning');
589+
document.body.appendChild(el);
590+
}
591+
592+
if (typeof console !== 'undefined' && typeof console.info === 'function') {
593+
console.info(
594+
'WARNING: You are using the Auth Emulator,' +
595+
' which is intended for local testing only. Do not use with' +
596+
' production credentials.'
597+
);
598+
}
599+
if (
600+
typeof window !== 'undefined' &&
601+
typeof document !== 'undefined' &&
602+
!disableBanner
603+
) {
604+
if (document.readyState === 'loading') {
605+
window.addEventListener('DOMContentLoaded', attachBanner);
606+
} else {
607+
attachBanner();
608+
}
609+
}
610+
}

packages-exp/auth-types-exp/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ export interface Auth {
316316
* traffic is not encrypted.
317317
*
318318
* @param url - The URL at which the emulator is running (eg, 'http://localhost:9099').
319+
* @param disableBanner - (Optional: default false) Disable the warning banner attached to the DOM
319320
*/
320-
useEmulator(url: string): void;
321+
useEmulator(url: string, options?: { disableWarnings: boolean }): void;
321322
/**
322323
* Signs out the current user.
323324
*/

0 commit comments

Comments
 (0)