Skip to content
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

test: Add permissions and roles e2e tests #4172

Merged
merged 85 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
c512014
test: Add permissions and roles e2e tests
novakzaballa Jun 12, 2024
cbdb48e
Update project-permissio-test
novakzaballa Jun 13, 2024
e13a27a
Update project and environments permissions
novakzaballa Jun 14, 2024
801e406
Add data-test property
novakzaballa Jun 18, 2024
10d2538
Role test
novakzaballa Jun 18, 2024
24e881d
Update the role test, and include permission and role test in the wor…
novakzaballa Jun 19, 2024
4a44fec
solve merge issues
novakzaballa Aug 12, 2024
6bb85fe
Merge branch 'main' into test/add-permissions-and-roles-e2e-tests
novakzaballa Aug 12, 2024
8db66c4
Merge branch 'main' into test/add-permissions-and-roles-e2e-tests
novakzaballa Aug 13, 2024
0cbc289
Solve roles test
novakzaballa Aug 15, 2024
83b3b2e
Add tag based permissions
kyle-ssg Sep 18, 2024
e838de4
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
matthewelwell Oct 7, 2024
e188231
Post merge additions
matthewelwell Oct 7, 2024
c8d4532
Merge branch 'refs/heads/main' into feat/tag-based-permissions
kyle-ssg Oct 8, 2024
58e6478
Merge
kyle-ssg Oct 8, 2024
dcef5ae
Tag based permissions flag
kyle-ssg Nov 5, 2024
82519f2
Add tag based permissions ui
kyle-ssg Nov 5, 2024
716706b
tag based role ui
kyle-ssg Nov 6, 2024
2c71cfa
Add tag_based_permissions logic to frontend
kyle-ssg Nov 6, 2024
3634609
Merge branch 'refs/heads/main' into feat/tag-based-permissions-valida…
kyle-ssg Nov 12, 2024
985cceb
Adjust tag base permissions data structure
kyle-ssg Nov 12, 2024
c09d39b
Adjust tag base permissions data structure
kyle-ssg Nov 12, 2024
a940e9a
Better permissions view for create feature
kyle-ssg Nov 12, 2024
750054b
Merge branch 'refs/heads/main' into feat/tag-based-permissions
kyle-ssg Nov 12, 2024
1837651
Merge branch 'refs/heads/main' into feat/tag-based-permissions
kyle-ssg Nov 12, 2024
48d54c5
Remove static tag_based variable
kyle-ssg Nov 12, 2024
f962c1c
Remove incorrect function call
kyle-ssg Nov 12, 2024
243c7a4
Adjust doc wording
kyle-ssg Nov 12, 2024
9ad625f
Merge branch 'refs/heads/main' into feat/tag-based-permissions
kyle-ssg Nov 13, 2024
bf5d177
Permissions v2
kyle-ssg Nov 13, 2024
72e5d8c
Tag based permissions UI
kyle-ssg Nov 19, 2024
195c400
Merge branch 'refs/heads/main' into feat/tag-based-permissions-v2
kyle-ssg Nov 19, 2024
d2b7011
Interop edit permissions / role-based permissions
kyle-ssg Nov 19, 2024
8482f89
Adjust UI for limited permissions
kyle-ssg Nov 19, 2024
29051be
LIMITED > GRANTED_FOR_TAGS
kyle-ssg Nov 19, 2024
23f5d18
Merge branch 'refs/heads/main' into feat/tag-based-permissions-v2
kyle-ssg Nov 27, 2024
7b2f458
Fix
kyle-ssg Nov 27, 2024
050f305
Integrate new API
kyle-ssg Dec 3, 2024
ae40fbc
Merge branch 'refs/heads/main' into feat/tag-based-permissions-v2
kyle-ssg Dec 3, 2024
f347559
Update docs
kyle-ssg Dec 3, 2024
6d986f3
Merge remote-tracking branch 'refs/remotes/origin/main' into test/add…
kyle-ssg Dec 3, 2024
f3e6082
Update tests
kyle-ssg Dec 3, 2024
2753ab8
Merge remote-tracking branch 'refs/remotes/origin/feat/tag-based-perm…
kyle-ssg Dec 3, 2024
db27e30
Merge tag based roles
kyle-ssg Dec 3, 2024
1422ab9
Merge tag based roles
kyle-ssg Dec 3, 2024
af13ff7
add tests
kyle-ssg Dec 3, 2024
244a675
Add tests
kyle-ssg Dec 4, 2024
f450416
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
kyle-ssg Dec 4, 2024
0b7b8da
more tests
kyle-ssg Dec 4, 2024
ec813ab
setuser permissions helper
kyle-ssg Dec 6, 2024
3c1a3f7
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
kyle-ssg Dec 10, 2024
a7be3f7
Remove debugger
kyle-ssg Dec 10, 2024
bc71237
Fix type and tags copy
kyle-ssg Dec 10, 2024
08b5795
Add tests for all project permissions
kyle-ssg Dec 10, 2024
44246b5
re-add tests
kyle-ssg Dec 10, 2024
00f935b
re-add tests
kyle-ssg Dec 10, 2024
976d675
Re-add all tests
kyle-ssg Dec 17, 2024
3a59576
Environment tests
kyle-ssg Dec 17, 2024
b73808a
Environment tests
kyle-ssg Dec 17, 2024
c296e92
Add environment permissions
kyle-ssg Dec 17, 2024
186ef91
Add environment permissions
kyle-ssg Dec 17, 2024
8767c78
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
kyle-ssg Dec 17, 2024
569fa9f
Don't fetch user overrides in edit feature if user has no permissions
kyle-ssg Dec 17, 2024
15edd44
More environment tests
kyle-ssg Dec 17, 2024
3543adc
More environment tests
kyle-ssg Dec 17, 2024
1e22b48
More environment tests
kyle-ssg Dec 17, 2024
2266221
feat: Run tests against private-cloud build on PRs and merge to main
khvn26 Dec 18, 2024
40ebb7b
Update flagsmith client api
kyle-ssg Jan 8, 2025
1a5d4c9
inherit secrets for e2e
kyle-ssg Jan 8, 2025
3bae43c
inherit secrets for e2e
kyle-ssg Jan 8, 2025
319ad8c
snake case gcr secret
kyle-ssg Jan 8, 2025
fb005f0
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
kyle-ssg Jan 8, 2025
2ea6c98
Adjust e2e org plan
kyle-ssg Jan 8, 2025
33b3d63
log plan and enterprise
kyle-ssg Jan 8, 2025
72a3d5a
hide e2e banner
kyle-ssg Jan 8, 2025
ab7e616
Fix view identities test
kyle-ssg Jan 8, 2025
7b34442
fix environment permissions test
kyle-ssg Jan 8, 2025
41c77e3
Fix e2e setup test
kyle-ssg Jan 8, 2025
84ff9a8
Fix roles test
kyle-ssg Jan 8, 2025
2a5a1b3
revert e2e css
kyle-ssg Jan 8, 2025
838ef73
fix role permissions
kyle-ssg Jan 14, 2025
43f5883
fix role permissions
kyle-ssg Jan 14, 2025
7924b16
Merge branch 'refs/heads/fix/role-permissions' into test/add-permissi…
kyle-ssg Jan 14, 2025
b4a1e18
Merge branch 'refs/heads/main' into test/add-permissions-and-roles-e2…
kyle-ssg Jan 21, 2025
860f923
Unused imports
kyle-ssg Jan 21, 2025
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
7 changes: 5 additions & 2 deletions .github/workflows/.reusable-docker-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ on:
required: false
default: ubuntu-latest
secrets:
gcr-token:
GCR_TOKEN:
description: A token to use for logging into Github Container Registry. If not provided, login does not occur.
required: false
SLACK_TOKEN:
description: A token to use uploading test failures to slack.
required: false

jobs:
run-e2e:
Expand All @@ -43,7 +46,7 @@ jobs:
id-token: write

env:
GCR_TOKEN: ${{ secrets.gcr-token }}
GCR_TOKEN: ${{ secrets.GCR_TOKEN }}

steps:
- name: Cloning repo
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/platform-docker-build-test-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ jobs:
concurrency: 2
- tests: versioning
concurrency: 1
- tests: organisation-permission environment-permission project-permission roles
concurrency: 1

docker-publish-api:
needs: [docker-build-api, run-e2e-tests]
Expand Down
24 changes: 23 additions & 1 deletion .github/workflows/platform-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ jobs:
concurrency: ${{ matrix.args.concurrency }}
tests: ${{ matrix.args.tests }}
secrets:
gcr-token: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
Expand All @@ -154,3 +155,24 @@ jobs:
concurrency: 2
- tests: versioning
concurrency: 1

run-e2e-tests-private-cloud:
if: needs.permissions-check.outputs.can-write == 'true' && !cancelled()
needs: [permissions-check, docker-build-private-cloud, docker-build-e2e]
uses: ./.github/workflows/.reusable-docker-e2e-tests.yml
with:
runs-on: ${{ matrix.runs-on }}
e2e-image: ${{ needs.docker-build-e2e.outputs.image }}
api-image: ${{ needs.docker-build-private-cloud.outputs.image }}
concurrency: ${{ matrix.args.concurrency }}
tests: ${{ matrix.args.tests }}
secrets:
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
runs-on: [ubuntu-latest, ARM64-2c]
args:
- tests: organisation-permission environment-permission project-permission roles
concurrency: 1
4 changes: 2 additions & 2 deletions api/e2etests/e2e_seed_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
CREATE_PROJECT,
MANAGE_USER_GROUPS,
)
from organisations.subscriptions.constants import SCALE_UP
from organisations.subscriptions.constants import ENTERPRISE
from projects.models import Project, UserProjectPermission
from users.models import FFAdminUser, UserPermissionGroup

Expand Down Expand Up @@ -129,7 +129,7 @@ def seed_data() -> None:
]
# Upgrade organisation seats
Subscription.objects.filter(organisation__in=org_admin.organisations.all()).update(
max_seats=8, plan=SCALE_UP, subscription_id="test_subscription_id"
max_seats=8, plan=ENTERPRISE, subscription_id="test_subscription_id"
)

# Create projects and environments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rest_framework.test import APIClient

from organisations.models import Subscription
from organisations.subscriptions.constants import SCALE_UP
from organisations.subscriptions.constants import ENTERPRISE
from users.models import FFAdminUser


Expand Down Expand Up @@ -43,7 +43,7 @@ def test_e2e_teardown(settings, db) -> None:
organisation__in=e2e_user.organisations.all()
):
assert subscription.max_seats == 8
assert subscription.plan == SCALE_UP
assert subscription.plan == ENTERPRISE
assert subscription.subscription_id == "test_subscription_id"


Expand Down
1 change: 1 addition & 0 deletions frontend/common/stores/organisation-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ store.dispatcherIndex = Dispatcher.register(store, (payload) => {
controller.invalidateInviteLink(action.link)
break
case Actions.LOGOUT:
store.model = null
store.id = null
break
default:
Expand Down
3 changes: 3 additions & 0 deletions frontend/common/stores/project-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ store.dispatcherIndex = Dispatcher.register(store, (payload) => {
case Actions.EDIT_PROJECT:
controller.editProject(action.id, action.project)
break
case Actions.LOGOUT:
store.model = null
break
default:
}
})
Expand Down
7 changes: 7 additions & 0 deletions frontend/e2e/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
const E2E_EMAIL_DOMAIN = 'flagsmithe2etestdomain.io'
export const E2E_SIGN_UP_USER = `e2e_signup_user@${E2E_EMAIL_DOMAIN}`
export const E2E_USER = `e2e_user@${E2E_EMAIL_DOMAIN}`
export const E2E_NON_ADMIN_USER = `e2e_user@${E2E_EMAIL_DOMAIN}`
//e2e_non_admin_user_with_project_permissions@flagsmithe2etestdomain.io
export const E2E_NON_ADMIN_USER_WITH_ORG_PERMISSIONS = `e2e_non_admin_user_with_org_permissions@${E2E_EMAIL_DOMAIN}`
export const E2E_NON_ADMIN_USER_WITH_PROJECT_PERMISSIONS = `e2e_non_admin_user_with_project_permissions@${E2E_EMAIL_DOMAIN}`
export const E2E_NON_ADMIN_USER_WITH_PROJECT_READ_PERMISSIONS = `e2e_non_admin_user_with_project_read_permissions@${E2E_EMAIL_DOMAIN}`
export const E2E_NON_ADMIN_USER_WITH_ENV_PERMISSIONS = `e2e_non_admin_user_with_env_permissions@${E2E_EMAIL_DOMAIN}`
export const E2E_NON_ADMIN_USER_WITH_A_ROLE = `e2e_non_admin_user_with_a_role@${E2E_EMAIL_DOMAIN}`
export const E2E_CHANGE_MAIL = `e2e_change_email@${E2E_EMAIL_DOMAIN}`
export const PASSWORD = 'Str0ngp4ssw0rd!'
107 changes: 106 additions & 1 deletion frontend/e2e/helpers.cafe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ export const waitForElementVisible = async (selector: string) => {
.ok(`waitForElementVisible(${selector})`, { timeout: LONG_TIMEOUT })
}

export const waitForElementNotClickable = async (selector: string) => {
logUsingLastSection(`Waiting element visible ${selector}`)
await t
.expect(Selector(selector).visible)
.ok(`waitForElementVisible(${selector})`, { timeout: LONG_TIMEOUT })
await t
.expect(Selector(selector).hasAttribute('disabled')).ok()
}

export const waitForElementClickable = async (selector: string) => {
logUsingLastSection(`Waiting element visible ${selector}`)
await t
.expect(Selector(selector).visible)
.ok(`waitForElementVisible(${selector})`, { timeout: LONG_TIMEOUT })
await t
.expect(Selector(selector).hasAttribute('disabled')).notOk()
}

export const logResults = async (requests: LoggedRequest[], t) => {
if (!t.testRun?.errs?.length) {
log('Finished without errors')
Expand Down Expand Up @@ -88,6 +106,17 @@ export const click = async (selector: string) => {
.click(selector)
}

export const clickByText = async (text:string, element = 'button') => {
logUsingLastSection(`Click by text ${text} ${element}`)
const selector = Selector(element).withText(text);
await t
.scrollIntoView(selector)
.expect(Selector(selector).hasAttribute('disabled'))
.notOk('ready for testing', { timeout: 5000 })
.hover(selector)
.click(selector)
}

export const gotoSegments = async () => {
await click('#segments-link')
}
Expand All @@ -102,6 +131,28 @@ export const getLogger = () =>
stringifyResponseBody: true,
})

export const createRole = async (roleName: string, index: number, users: number[]) => {
await click(byId('tab-item-roles'))
await click(byId('create-role'))
await setText(byId('role-name'), roleName)
await click(byId('save-role'))
await click(byId(`role-${index}`))
await click(byId('members-tab'))
await click(byId('assigned-users'))
for (const userId of users) {
await click(byId(`assignees-list-item-${userId}`))
}
await closeModal()
}


export const editRoleMembers = async (index:number)=>{
await click(byId('tab-item-roles'))
await click(byId('create-role'))
await setText(byId('role-name'), roleName)
await click(byId('save-role'))
}

export const gotoTraits = async () => {
await click('#features-link')
await click('#users-link')
Expand Down Expand Up @@ -219,6 +270,12 @@ export const saveFeatureSegments = async () => {
await waitForElementNotExist('#create-feature-modal')
}

export const createEnvironment = async (name:string) => {
await setText('[name="envName"]', name)
await click('#create-env-btn')
await waitForElementVisible(byId(`switch-environment-${name.toLowerCase()}-active`))
}

export const goToUser = async (index: number) => {
await click('#features-link')
await click('#users-link')
Expand Down Expand Up @@ -257,7 +314,7 @@ export const login = async (email: string, password: string) => {
await click('#login-btn')
await waitForElementVisible('#project-manage-widget')
}
export const logout = async (t) => {
export const logout = async () => {
await click('#account-settings-link')
await click('#logout-link')
await waitForElementVisible('#login-page')
Expand Down Expand Up @@ -413,6 +470,14 @@ export const toggleFeature = async (index: number, toValue: boolean) => {
)
}

export const setUserPermissions = async (index: number, toValue: boolean) => {
await click(byId(`feature-switch-${index}${toValue ? '-off' : 'on'}`))
await click('#confirm-toggle-feature-btn')
await waitForElementVisible(
byId(`feature-switch-${index}${toValue ? '-on' : 'off'}`),
)
}

export const setSegmentRule = async (
ruleIndex: number,
orIndex: number,
Expand Down Expand Up @@ -478,4 +543,44 @@ export const refreshUntilElementVisible = async (selector: string, maxRetries=20
return t.scrollIntoView(element)
}

const permissionsMap = {
'CREATE_PROJECT': 'organisation',
'MANAGE_USERS': 'organisation',
'MANAGE_USER_GROUPS': 'organisation',
'VIEW_PROJECT': 'project',
'CREATE_ENVIRONMENT': 'project',
'DELETE_FEATURE': 'project',
'CREATE_FEATURE': 'project',
'MANAGE_SEGMENTS': 'project',
'VIEW_AUDIT_LOG': 'project',
'VIEW_ENVIRONMENT': 'environment',
'UPDATE_FEATURE_STATE': 'environment',
'MANAGE_IDENTITIES': 'environment',
'CREATE_CHANGE_REQUEST': 'environment',
'APPROVE_CHANGE_REQUEST': 'environment',
'VIEW_IDENTITIES': 'environment',
'MANAGE_SEGMENT_OVERRIDES': 'environment',
'MANAGE_TAGS': 'project',
} as const;


export const setUserPermission = async (email: string, permission: keyof typeof permissionsMap | 'ADMIN', entityName:string|null, entityLevel?: 'project'|'environment'|'organisation', parentName?: string) => {
await click(byId('users-and-permissions'))
await click(byId(`user-${email}`))
const level = permissionsMap[permission] || entityLevel
await click(byId(`${level}-permissions-tab`))
if(parentName) {
await clickByText(parentName, 'a')
}
if(entityName) {
await click(byId(`permissions-${entityName.toLowerCase()}`))
}
if(permission==='ADMIN') {
await click(byId(`admin-switch-${level}`))
} else {
await click(byId(`permission-switch-${permission}`))
}
await closeModal()
}

export default {}
13 changes: 9 additions & 4 deletions frontend/e2e/index.cafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@ createTestCafe()
testcafe = tc;
await new Promise((resolve) => {
process.env.PORT = 3000;
server = fork('./api/index');
server.on('message', () => {
resolve();
});
console.log(process.env.E2E_LOCAL)
if(process.env.E2E_LOCAL) {
resolve()
} else {
server = fork('./api/index');
server.on('message', () => {
resolve();
});
}
});
const runner = testcafe.createRunner()
const args = process.argv.splice(2).map(value => value.toLowerCase());
Expand Down
21 changes: 20 additions & 1 deletion frontend/e2e/init.cafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import projectTest from './tests/project-test'
import { testSegment1, testSegment2, testSegment3 } from './tests/segment-test'
import initialiseTests from './tests/initialise-tests'
import flagTests from './tests/flag-tests'
import versioningTests from './tests/versioning-tests';
import versioningTests from './tests/versioning-tests'
import organisationPermissionTest from './tests/organisation-permission-test'
import projectPermissionTest from './tests/project-permission-test'
import environmentPermissionTest from './tests/environment-permission-test'
import rolesTest from './tests/roles-test'

require('dotenv').config()

Expand Down Expand Up @@ -124,3 +128,18 @@ test('Versioning', async () => {
await versioningTests()
await logout()
})

test('Organisation-permission', async () => {
await organisationPermissionTest()
await logout()
})

test('Project-permission', async () => {
await projectPermissionTest()
await logout()
})

test('Environment-permission', async () => {
await environmentPermissionTest()
await logout()
})
Loading
Loading