Skip to content
Open
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
37 changes: 36 additions & 1 deletion frontend/web/__tests__/routePaths.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
import { isAllowedWhileBlocked, isOrganisationUsage } from 'web/routePaths'
import AccountStore from 'common/stores/account-store'
import {
isAllowedWhileBlocked,
isOrganisationUsage,
shouldShowOrganisationLimit,
} from 'web/routePaths'

jest.mock('common/stores/account-store', () => ({
__esModule: true,
default: { isAdmin: jest.fn() },
}))

const mockIsAdmin = AccountStore.isAdmin as jest.Mock

beforeEach(() => {
mockIsAdmin.mockReset()
})

// App renders <Blocked /> wherever this is false, so a wrong answer either
// locks a blocked organisation out, or lets it back in.
Expand Down Expand Up @@ -27,6 +43,25 @@ describe('isAllowedWhileBlocked', () => {
})
})

describe('shouldShowOrganisationLimit', () => {
it.each`
isAdmin | pathname | usageDashboardEnabled | shouldShow
${true} | ${'/organisation/7528/usage'} | ${false} | ${true}
${true} | ${'/organisation/7528/usage'} | ${true} | ${false}
${true} | ${'/organisation/7528/projects'} | ${true} | ${true}
${false} | ${'/organisation/7528/usage'} | ${false} | ${false}
${false} | ${'/organisation/7528/projects'} | ${true} | ${false}
`(
'admin=$isAdmin, pathname=$pathname, usage dashboard=$usageDashboardEnabled: $shouldShow',
({ isAdmin, pathname, shouldShow, usageDashboardEnabled }) => {
mockIsAdmin.mockReturnValue(isAdmin)
expect(shouldShowOrganisationLimit(pathname, usageDashboardEnabled)).toBe(
shouldShow,
)
},
)
})

Comment on lines +46 to +64

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trivial · Maintainability & Code Quality · Low value

Supported by static analysis

Script executed:

rg -n 'OrganisationLimit|shouldShowOrganisationLimit|AccountStore\.isAdmin\(' frontend/web/__tests__ frontend/web/components -g '*test*' -g '*spec*' | head -100

Repository: Flagsmith/flagsmith

Length of output: 446


Script executed:

git diff 13539afcb99c20b4351e26f215d01b49f2a9be03 8a060f262bca1f704f9d6c69365d92c6591a0e36 -- frontend/web/routePaths.ts frontend/web/components/App.js frontend/web/__tests__/routePaths.test.ts
printf '\n--- source files ---\n'
nl -ba frontend/web/__tests__/routePaths.test.ts | sed -n '1,160p'
nl -ba frontend/web/routePaths.ts | sed -n '1,160p'
nl -ba frontend/web/components/App.js | sed -n '1,110p;300,410p'
printf '\n--- test references ---\n'
rg -n -i -e 'OrganisationLimit' -e 'shouldShowOrganisationLimit' -e 'over.limit' -e 'quota banner' -e 'isAdmin' frontend --glob '*test*' --glob '*spec*' || test "$?" -eq 1

Repository: Flagsmith/flagsmith

Length of output: 17041


Script executed:

printf '%s\n' '--- App route and render context ---'
nl -ba frontend/web/components/App.js | sed -n '255,305p'
printf '%s\n' '--- OrganisationLimit source ---'
rg --files frontend/web/components -g 'OrganisationLimit*'
nl -ba frontend/web/components/OrganisationLimit.js | sed -n '1,220p'
printf '%s\n' '--- banner and App test candidates repository-wide ---'
rg -n -i -e 'OrganisationLimit' -e 'shouldShowOrganisationLimit' -e 'over.limit' -e 'quota banner' -e 'usage limit' --glob '!*.lock' --glob '!*.po' --glob '!*.json' --glob '!*.svg' --glob '*test*' --glob '*spec*' . || test "$?" -eq 1
printf '%s\n' '--- browser test directories and references ---'
rg --files | rg -i '(^|/)(cypress|e2e|playwright|integration)/|(^|/)[^/]*(app|usage)[^/]*\.(test|spec)\.'

Repository: Flagsmith/flagsmith

Length of output: 11554


Script executed:

nl -ba frontend/web/components/OrganisationLimit.tsx | sed -n '1,240p'
printf '\n--- Playwright quota and usage references ---\n'
rg -n -i -e 'quota' -e 'usage' -e 'limit' -e 'banner' -e 'organisationlimit' frontend/e2e/tests frontend/e2e/helpers || test "$?" -eq 1
printf '\n--- App imports in frontend tests ---\n'
rg -n -e "components/App" -e "from ['\"].*App['\"]" -e '<App[ />]' frontend --glob '*.test.*' --glob '*.spec.*' --glob '*.pw.ts' || test "$?" -eq 1

Repository: Flagsmith/flagsmith

Length of output: 4291


Test banner visibility through App.

Add rendered-banner tests for signed-in admins and non-admins on usage and non-usage routes. These helper tests pass literal booleans, so they would still pass if App supplied the wrong role or used the result incorrectly.

// App hides its app-wide quota banner here, where the page has its own.
describe('isOrganisationUsage', () => {
it.each`
Expand Down
16 changes: 8 additions & 8 deletions frontend/web/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import Announcement from './Announcement'
import { getBuildVersion } from 'common/services/useBuildVersion'
import AccountProvider from 'common/providers/AccountProvider'
import Nav from './navigation/Nav'
import { isAllowedWhileBlocked, isOrganisationUsage } from 'web/routePaths'
import {
isAllowedWhileBlocked,
shouldShowOrganisationLimit,
} from 'web/routePaths'
import 'project/darkMode'

const App = class extends Component {
Expand Down Expand Up @@ -269,12 +272,6 @@ const App = class extends Component {
pathname === '/getting-started' &&
getStoredOnboardingVariant() === 'single_page'

// The usage dashboard says the same thing in its own banner, with the
// detail this one cannot reach.
const hasOwnQuotaBanner =
isOrganisationUsage(pathname) &&
Utils.getFlagsmithHasFeature('usage_dashboard')

const projectId = this.getProjectId(this.props)
const environmentId = this.getEnvironmentId(this.props)

Expand Down Expand Up @@ -366,7 +363,10 @@ const App = class extends Component {
/>
{user && (
<>
{!hasOwnQuotaBanner && (
{shouldShowOrganisationLimit(
pathname,
Utils.getFlagsmithHasFeature('usage_dashboard'),
) && (
<OrganisationLimit
id={AccountStore.getOrganisation()?.id}
organisationPlan={
Expand Down
8 changes: 8 additions & 0 deletions frontend/web/routePaths.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { matchPath } from 'react-router-dom'
import AccountStore from 'common/stores/account-store'

// Kept out of web/routes, which imports App: reading a path from there in a
// component is a cycle, and it took the app down once.
Expand All @@ -17,3 +18,10 @@ export const isAllowedWhileBlocked = (pathname: string): boolean =>

export const isOrganisationUsage = (pathname: string): boolean =>
matches(pathname, ORGANISATION_USAGE)

export const shouldShowOrganisationLimit = (
pathname: string,
usageDashboardEnabled: boolean,
): boolean =>
Boolean(AccountStore.isAdmin()) &&
!(isOrganisationUsage(pathname) && usageDashboardEnabled)