Skip to content

Commit b445235

Browse files
jlengstorfcassidooerezrokah
authored
fix: prevent double initialization (#284)
* feat: add support for unregistering event handlers Refactor callback management to use `Map` so that we can unregister handlers without changing the current behavior. Co-authored-by: Cassidy Williams <[email protected]> * fix: use a Set instead of a Map * chore: add Prettier config * fix: prevent double initialization * fix: don't call init event twice when on localhost GoTrue was instantiated twice when on localhost and netlifySiteURL configured Co-authored-by: Cassidy Williams <[email protected]> Co-authored-by: erezrokah <[email protected]>
1 parent 9ef4305 commit b445235

File tree

3 files changed

+71
-43
lines changed

3 files changed

+71
-43
lines changed

.prettierrc.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
semi: true,
3+
singleQuote: false,
4+
trailingComma: "none",
5+
tabWidth: 2
6+
};

src/netlify-identity.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,17 @@ const localHosts = {
9494
};
9595

9696
function instantiateGotrue(APIUrl) {
97-
const isLocal = localHosts[document.location.host.split(":").shift()];
98-
const siteURL = isLocal && localStorage.getItem("netlifySiteURL");
97+
const isLocal = localHosts[document.location.hostname];
9998
if (APIUrl) {
10099
return new GoTrue({ APIUrl, setCookie: !isLocal });
101100
}
102-
if (isLocal && siteURL) {
103-
const parts = [siteURL];
104-
if (!siteURL.match(/\/$/)) {
105-
parts.push("/");
106-
}
107-
parts.push(".netlify/identity");
108-
store.setIsLocal(isLocal);
109-
store.setSiteURL(siteURL);
110-
return new GoTrue({ APIUrl: parts.join(""), setCookie: !isLocal });
111-
}
112101
if (isLocal) {
113102
store.setIsLocal(isLocal);
103+
const siteURL = localStorage.getItem("netlifySiteURL");
104+
if (siteURL) {
105+
// setting a siteURL will invoke instantiateGotrue again with the relevant APIUrl
106+
store.setSiteURL(siteURL);
107+
}
114108
return null;
115109
}
116110

@@ -153,7 +147,13 @@ observe(store, "siteURL", () => {
153147
} else {
154148
localStorage.setItem("netlifySiteURL", store.siteURL);
155149
}
156-
store.init(instantiateGotrue(), true);
150+
151+
let apiUrl;
152+
if (store.siteURL) {
153+
const siteUrl = store.siteURL.replace(/\/$/, "");
154+
apiUrl = `${siteUrl}/.netlify/identity`;
155+
}
156+
store.init(instantiateGotrue(apiUrl), true);
157157
});
158158

159159
observe(store, "user", () => {

src/netlify-identity.test.js

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
jest.mock("./components/modal.css", () => "");
2+
jest.mock("gotrue-js", () => {
3+
const mock = jest.fn().mockImplementation(({ APIUrl, setCookie }) => {
4+
return {
5+
settings: jest.fn().mockResolvedValue({
6+
external: {
7+
bitbucket: false,
8+
github: false,
9+
gitlab: false,
10+
google: false,
11+
facebook: false,
12+
email: true,
13+
saml: false
14+
},
15+
external_labels: {},
16+
disable_signup: false,
17+
autoconfirm: false
18+
}),
19+
currentUser: jest.fn(),
20+
APIUrl,
21+
setCookie
22+
};
23+
});
24+
return mock;
25+
});
226

327
describe("netlifyIdentity", () => {
428
beforeEach(() => {
529
jest.resetModules();
6-
jest.mock("./state/store", () => {
7-
const { observable } = require("mobx");
8-
const store = observable({
9-
user: null,
10-
recovered_user: null,
11-
message: null,
12-
settings: null,
13-
gotrue: null,
14-
error: null,
15-
siteURL: null,
16-
remember: true,
17-
saving: false,
18-
invite_token: null,
19-
email_change_token: null,
20-
namePlaceholder: null,
21-
modal: {
22-
page: "login",
23-
isOpen: false,
24-
logo: true
25-
},
26-
locale: "en"
27-
});
28-
return store;
29-
});
3030
});
3131

3232
describe("on", () => {
3333
it("should invoke login callback when user is set to an object", () => {
34-
const store = require("./state/store");
34+
const { default: store } = require("./state/store");
3535
const { default: netlifyIdentity } = require("./netlify-identity");
3636

3737
const loginCallback = jest.fn();
@@ -46,7 +46,7 @@ describe("netlifyIdentity", () => {
4646
});
4747

4848
it("should invoke logout callback when user is set to null", () => {
49-
const store = require("./state/store");
49+
const { default: store } = require("./state/store");
5050
store.user = {
5151
name: "user"
5252
};
@@ -62,7 +62,7 @@ describe("netlifyIdentity", () => {
6262
});
6363

6464
it("should not invoke login callback when user is set to null", () => {
65-
const store = require("./state/store");
65+
const { default: store } = require("./state/store");
6666
store.user = {
6767
name: "user"
6868
};
@@ -78,7 +78,7 @@ describe("netlifyIdentity", () => {
7878
});
7979

8080
it("should not invoke logout callback when user is set to an object", () => {
81-
const store = require("./state/store");
81+
const { default: store } = require("./state/store");
8282
store.user = null;
8383

8484
const { default: netlifyIdentity } = require("./netlify-identity");
@@ -102,7 +102,7 @@ describe("netlifyIdentity", () => {
102102
});
103103

104104
it("should remove all callbacks when called with only first argument", () => {
105-
const store = require("./state/store");
105+
const { default: store } = require("./state/store");
106106
const { default: netlifyIdentity } = require("./netlify-identity");
107107

108108
const loginCallback1 = jest.fn();
@@ -132,7 +132,7 @@ describe("netlifyIdentity", () => {
132132
});
133133

134134
it("should remove a specific callback when called with two arguments", () => {
135-
const store = require("./state/store");
135+
const { default: store } = require("./state/store");
136136
const { default: netlifyIdentity } = require("./netlify-identity");
137137

138138
const loginCallback1 = jest.fn();
@@ -161,4 +161,26 @@ describe("netlifyIdentity", () => {
161161
expect(loginCallback2).toHaveBeenCalledTimes(1);
162162
});
163163
});
164+
165+
describe("init", () => {
166+
it("should only invoke init event once when on localhost and netlifySiteURL is set", () => {
167+
window.location = { hostname: "localhost" };
168+
localStorage.setItem("netlifySiteURL", "https://my-site.netlify.app/");
169+
170+
const { default: store } = require("./state/store");
171+
const { default: netlifyIdentity } = require("./netlify-identity");
172+
173+
const initCallback = jest.fn();
174+
netlifyIdentity.on("init", initCallback);
175+
176+
netlifyIdentity.init();
177+
178+
expect(initCallback).toHaveBeenCalledTimes(1);
179+
expect(store.siteURL).toEqual("https://my-site.netlify.app/");
180+
expect(store.gotrue.APIUrl).toEqual(
181+
"https://my-site.netlify.app/.netlify/identity"
182+
);
183+
expect(store.gotrue.setCookie).toEqual(false);
184+
});
185+
});
164186
});

0 commit comments

Comments
 (0)