Skip to content

Commit

Permalink
Merge pull request #1146 from kwojtasinski-repo/1134_automatic_close_…
Browse files Browse the repository at this point in the history
…window_after_some_time

 #1134  Add possibility to automatically close popup window after som…
  • Loading branch information
pamapa authored Sep 1, 2023
2 parents d1c9354 + 10b57ab commit 460578d
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/oidc-client-ts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ export interface OidcStandardClaims {
export interface PopupWindowFeatures {
// (undocumented)
[k: string]: boolean | string | number | undefined;
closePopupWindowAfterInSeconds?: number;
// (undocumented)
height?: number;
// (undocumented)
Expand Down
13 changes: 13 additions & 0 deletions src/UserManagerSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ describe("UserManagerSettings", () => {
expect(subject.popupWindowFeatures).toEqual({ status: true });
});

it("should set closePopupWindowAfterInMilliseconds", () => {
// act
const closePopupWindowAfterInSeconds = 100;
const subject = new UserManagerSettingsStore({
authority: "authority",
client_id: "client",
redirect_uri: "redirect",
popupWindowFeatures: { status: true, closePopupWindowAfterInSeconds },
});

// assert
expect(subject.popupWindowFeatures).toEqual({ status: true, closePopupWindowAfterInSeconds });
});
});

describe("popupWindowTarget", () => {
Expand Down
3 changes: 2 additions & 1 deletion src/UserManagerSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const DefaultPopupWindowFeatures: PopupWindowFeatures = {
location: false,
toolbar: false,
height: 640,
closePopupWindowAfterInSeconds: -1,
};
export const DefaultPopupTarget = "_blank";
const DefaultAccessTokenExpiringNotificationTimeInSeconds = 60;
Expand All @@ -28,7 +29,7 @@ export interface UserManagerSettings extends OidcClientSettings {
/**
* The features parameter to window.open for the popup signin window. By default, the popup is
* placed centered in front of the window opener.
* (default: \{ location: false, menubar: false, height: 640 \})
* (default: \{ location: false, menubar: false, height: 640, closePopupWindowAfterInSeconds: -1 \})
*/
popupWindowFeatures?: PopupWindowFeatures;
/** The target parameter to window.open for the popup signin window (default: "_blank") */
Expand Down
28 changes: 28 additions & 0 deletions src/navigators/PopupWindow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,32 @@ describe("PopupWindow", () => {
keepOpen: false,
}, window.location.origin);
});

it("should close the window after closePopupWindowAfter is greater than 0", async () => {
const popupWindow = new PopupWindow({ popupWindowFeatures: { closePopupWindowAfterInSeconds: 1 } });

const promise = popupWindow.navigate({ url: "http://sts/authorize?x=y", state: "someid" });

jest.runOnlyPendingTimers();
await expect(promise).rejects.toThrow("Popup blocked by user");
jest.runAllTimers();
});

it("shouldnt close the window after closePopupWindowAfter is equal to 0", async () => {
jest.spyOn(global, "setTimeout");

new PopupWindow({ popupWindowFeatures: { closePopupWindowAfterInSeconds: 0 } });

jest.runOnlyPendingTimers();
expect(setTimeout).toHaveBeenCalledTimes(0);
});

it("shouldnt close the window after closePopupWindowAfter is less than 0", async () => {
jest.spyOn(global, "setTimeout");

new PopupWindow({ popupWindowFeatures: { closePopupWindowAfterInSeconds: -120 } });

jest.runOnlyPendingTimers();
expect(setTimeout).toHaveBeenCalledTimes(0);
});
});
8 changes: 8 additions & 0 deletions src/navigators/PopupWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AbstractChildWindow } from "./AbstractChildWindow";
import type { NavigateParams, NavigateResponse } from "./IWindow";

const checkForPopupClosedInterval = 500;
const second = 1000;

/**
* @public
Expand All @@ -31,6 +32,13 @@ export class PopupWindow extends AbstractChildWindow {
super();
const centeredPopup = PopupUtils.center({ ...DefaultPopupWindowFeatures, ...popupWindowFeatures });
this._window = window.open(undefined, popupWindowTarget, PopupUtils.serialize(centeredPopup));
if (popupWindowFeatures.closePopupWindowAfterInSeconds && popupWindowFeatures.closePopupWindowAfterInSeconds > 0) {
setTimeout(() => {
if (!this._window || typeof this._window.closed !== "boolean" || this._window.closed) {
this._abort.raise(new Error("Popup blocked by user"));
}
}, popupWindowFeatures.closePopupWindowAfterInSeconds * second);
}
}

public async navigate(params: NavigateParams): Promise<NavigateResponse> {
Expand Down
2 changes: 2 additions & 0 deletions src/utils/PopupUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface PopupWindowFeatures {
status?: boolean | string;
resizable?: boolean | string;
scrollbars?: boolean | string;
/** Close popup window after time in seconds, by default it is -1. To enable this feature set value greater than 0 */
closePopupWindowAfterInSeconds?: number;

[k: string]: boolean | string | number | undefined;
}
Expand Down

0 comments on commit 460578d

Please sign in to comment.