Skip to content

fix: prevent double initialization #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
semi: true,
singleQuote: false,
trailingComma: "none",
tabWidth: 2
};
26 changes: 13 additions & 13 deletions src/netlify-identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,17 @@ const localHosts = {
};

function instantiateGotrue(APIUrl) {
const isLocal = localHosts[document.location.host.split(":").shift()];
const siteURL = isLocal && localStorage.getItem("netlifySiteURL");
const isLocal = localHosts[document.location.hostname];
if (APIUrl) {
return new GoTrue({ APIUrl, setCookie: !isLocal });
}
if (isLocal && siteURL) {
const parts = [siteURL];
if (!siteURL.match(/\/$/)) {
parts.push("/");
}
parts.push(".netlify/identity");
store.setIsLocal(isLocal);
store.setSiteURL(siteURL);
return new GoTrue({ APIUrl: parts.join(""), setCookie: !isLocal });
}
if (isLocal) {
store.setIsLocal(isLocal);
const siteURL = localStorage.getItem("netlifySiteURL");
if (siteURL) {
// setting a siteURL will invoke instantiateGotrue again with the relevant APIUrl
store.setSiteURL(siteURL);
}
return null;
}

Expand Down Expand Up @@ -153,7 +147,13 @@ observe(store, "siteURL", () => {
} else {
localStorage.setItem("netlifySiteURL", store.siteURL);
}
store.init(instantiateGotrue(), true);

let apiUrl;
if (store.siteURL) {
const siteUrl = store.siteURL.replace(/\/$/, "");
apiUrl = `${siteUrl}/.netlify/identity`;
}
store.init(instantiateGotrue(apiUrl), true);
});

observe(store, "user", () => {
Expand Down
82 changes: 52 additions & 30 deletions src/netlify-identity.test.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
jest.mock("./components/modal.css", () => "");
jest.mock("gotrue-js", () => {
const mock = jest.fn().mockImplementation(({ APIUrl, setCookie }) => {
return {
settings: jest.fn().mockResolvedValue({
external: {
bitbucket: false,
github: false,
gitlab: false,
google: false,
facebook: false,
email: true,
saml: false
},
external_labels: {},
disable_signup: false,
autoconfirm: false
}),
currentUser: jest.fn(),
APIUrl,
setCookie
};
});
return mock;
});

describe("netlifyIdentity", () => {
beforeEach(() => {
jest.resetModules();
jest.mock("./state/store", () => {
const { observable } = require("mobx");
const store = observable({
user: null,
recovered_user: null,
message: null,
settings: null,
gotrue: null,
error: null,
siteURL: null,
remember: true,
saving: false,
invite_token: null,
email_change_token: null,
namePlaceholder: null,
modal: {
page: "login",
isOpen: false,
logo: true
},
locale: "en"
});
return store;
});
});

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

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

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

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

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

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

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

const loginCallback1 = jest.fn();
Expand Down Expand Up @@ -132,7 +132,7 @@ describe("netlifyIdentity", () => {
});

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

const loginCallback1 = jest.fn();
Expand Down Expand Up @@ -161,4 +161,26 @@ describe("netlifyIdentity", () => {
expect(loginCallback2).toHaveBeenCalledTimes(1);
});
});

describe("init", () => {
it("should only invoke init event once when on localhost and netlifySiteURL is set", () => {
window.location = { hostname: "localhost" };
localStorage.setItem("netlifySiteURL", "https://my-site.netlify.app/");

const { default: store } = require("./state/store");
const { default: netlifyIdentity } = require("./netlify-identity");

const initCallback = jest.fn();
netlifyIdentity.on("init", initCallback);

netlifyIdentity.init();

expect(initCallback).toHaveBeenCalledTimes(1);
expect(store.siteURL).toEqual("https://my-site.netlify.app/");
expect(store.gotrue.APIUrl).toEqual(
"https://my-site.netlify.app/.netlify/identity"
);
expect(store.gotrue.setCookie).toEqual(false);
});
});
});