-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DX: Split out feature flags from the Me user data endpoint (#7734)
* split out feature flags from Me endpoint * add new file to null checks * fix tests * Update src/auth/featureFlags.ts Co-authored-by: Graham Langford <30706330+grahamlangford@users.noreply.github.com> * add comment back * clean up * add tests * add test file to null checks * some pr feedback * reset feature flags on auth change * make sure flag is cleared * convert to use webext-storage-cache * fix jest config, fix storage override, update snapshots * package lock changes? * move feature flag fetch to background, and add useFlags tests * fix manifest snapshot * fix package lock * Add CI check * Add unique identifiers * restore lockfile * /2 * Automatically hide comment once resolved * Test strictNullChecks CI check for messenger * Drop CI workflows from this PR, move to their own PRs * `fetchFeatureFlags` - Use readonly array * `fetchFeatureFlags` - Drop redundant HTTP status check Axios already throws on HTTP errors * remove maxAge/expiry timeouts * package lock * fix strict null checks with messenger call * remove test function * fix import and add file to null checks --------- Co-authored-by: Ben Loe <ben@pixiebrix.com> Co-authored-by: Graham Langford <30706330+grahamlangford@users.noreply.github.com> Co-authored-by: Todd Schiller <todd.schiller@gmail.com> Co-authored-by: Federico Brigante <me@fregante.com>
- Loading branch information
1 parent
cbd7760
commit c50ddca
Showing
64 changed files
with
547 additions
and
188 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright (C) 2024 PixieBrix, Inc. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
import { | ||
fetchFeatureFlags, | ||
flagOn, | ||
resetFeatureFlags, | ||
TEST_overrideFeatureFlags, | ||
} from "@/auth/featureFlagStorage"; | ||
import { appApiMock } from "@/testUtils/appApiMock"; | ||
import { TEST_setAuthData, TEST_triggerListeners } from "@/auth/authStorage"; | ||
import { tokenAuthDataFactory } from "@/testUtils/factories/authFactories"; | ||
import { fetchFeatureFlagsInBackground } from "@/background/messenger/strict/api"; | ||
|
||
describe("featureFlags", () => { | ||
beforeEach(async () => { | ||
// Wire up the real fetch function so we can mock the api responses | ||
jest | ||
.mocked(fetchFeatureFlagsInBackground) | ||
.mockImplementation(fetchFeatureFlags); | ||
appApiMock.reset(); | ||
appApiMock.onGet("/api/me/").reply(200, { | ||
flags: [], | ||
}); | ||
}); | ||
|
||
afterEach(async () => { | ||
await resetFeatureFlags(); | ||
}); | ||
|
||
it("returns true if flag is present", async () => { | ||
// eslint-disable-next-line new-cap | ||
await TEST_overrideFeatureFlags([ | ||
"test-flag", | ||
"test-other-flag", | ||
"test-other-flag-2", | ||
]); | ||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
}); | ||
|
||
it("returns false if flag is not present", async () => { | ||
// eslint-disable-next-line new-cap | ||
await TEST_overrideFeatureFlags(["test-other-flag", "test-other-flag-2"]); | ||
await expect(flagOn("test-flag")).resolves.toBe(false); | ||
}); | ||
|
||
it("fetches flags on initial storage state", async () => { | ||
appApiMock.onGet("/api/me/").reply(200, { | ||
flags: ["test-flag"], | ||
}); | ||
|
||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
expect(appApiMock.history.get).toHaveLength(1); | ||
}); | ||
|
||
it("does not fetch if flags have been updated recently", async () => { | ||
// eslint-disable-next-line new-cap | ||
await TEST_overrideFeatureFlags(["test-flag"]); | ||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
expect(appApiMock.history.get).toHaveLength(0); | ||
}); | ||
|
||
it("only fetches once if multiple calls are made", async () => { | ||
appApiMock.onGet("/api/me/").reply(200, { | ||
flags: ["test-flag"], | ||
}); | ||
|
||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
await expect(flagOn("test-flag")).resolves.toBe(true); | ||
expect(appApiMock.history.get).toHaveLength(1); | ||
}); | ||
|
||
it("fetches flags again if auth is reset in between calls", async () => { | ||
appApiMock.onGet("/api/me/").reply(200, { | ||
flags: ["test-flag", "secret-flag"], | ||
}); | ||
|
||
await expect(flagOn("secret-flag")).resolves.toBe(true); | ||
await expect(flagOn("secret-flag")).resolves.toBe(true); | ||
expect(appApiMock.history.get).toHaveLength(1); | ||
|
||
const authData = tokenAuthDataFactory(); | ||
// eslint-disable-next-line new-cap | ||
await TEST_setAuthData(authData); | ||
// eslint-disable-next-line new-cap | ||
TEST_triggerListeners(authData); | ||
|
||
// New user doesn't have secret flag | ||
appApiMock.onGet("/api/me/").reply(200, { | ||
flags: ["test-flag"], | ||
}); | ||
|
||
await expect(flagOn("secret-flag")).resolves.toBe(false); | ||
await expect(flagOn("secret-flag")).resolves.toBe(false); | ||
expect(appApiMock.history.get).toHaveLength(2); | ||
}); | ||
}); |
Oops, something went wrong.