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

feat(flags): Set up initial backend for feature management #26628

Open
wants to merge 131 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
0846ff6
feat(flags): Set up initial UI-reorganization for feature management
havenbarnes Nov 22, 2024
b345652
tweak
havenbarnes Nov 22, 2024
0e42571
properly handle New Feature / New Flag -> Cancel navigation
havenbarnes Nov 23, 2024
7bd1ee1
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Nov 23, 2024
32a11e2
handle breadcrumbs properly based on ff
havenbarnes Nov 23, 2024
3c45f0e
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Nov 25, 2024
e2300bc
Merge branch 'master' into feature-management-ui-setup
havenbarnes Nov 25, 2024
0a2294a
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Nov 26, 2024
b2c36b8
cleanup
havenbarnes Nov 26, 2024
745bad1
tweak
havenbarnes Nov 26, 2024
b20b91c
Merge branch 'feature-management-ui-setup' of https://github.com/Post…
havenbarnes Nov 26, 2024
dbba27e
tweak
havenbarnes Nov 26, 2024
4419ec0
tweak
havenbarnes Nov 26, 2024
c07d6d4
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 2, 2024
e98fc0d
Re-worked with master-detail pattern
havenbarnes Dec 3, 2024
3d35964
tweak
havenbarnes Dec 3, 2024
75181d7
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 3, 2024
0bef6a7
tweak
havenbarnes Dec 3, 2024
00a837b
stash
havenbarnes Dec 3, 2024
8f1e249
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 3, 2024
19719f4
stash
havenbarnes Dec 3, 2024
38a761f
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 3, 2024
9008eb5
Initial endpoints, still needs tests and FE integration
havenbarnes Dec 4, 2024
31fa157
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 4, 2024
c0d5fdf
Merge branch 'feature-management-ui-setup' of https://github.com/Post…
havenbarnes Dec 4, 2024
199b552
Add tests for feature viewset
havenbarnes Dec 4, 2024
00b3f8b
tweak
havenbarnes Dec 4, 2024
a51dd17
Update query snapshots
github-actions[bot] Dec 4, 2024
38a52c9
tweak
havenbarnes Dec 4, 2024
8902068
Update query snapshots
github-actions[bot] Dec 4, 2024
5c077e8
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 4, 2024
f70dfb8
Update query snapshots
github-actions[bot] Dec 4, 2024
a3a7a3c
Update query snapshots
github-actions[bot] Dec 4, 2024
6c3e7f8
address comment
havenbarnes Dec 5, 2024
050d44f
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 5, 2024
aad2381
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 5, 2024
d1985e5
Merge branch 'feature-management-ui-setup' of https://github.com/Post…
havenbarnes Dec 5, 2024
ca7ead8
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 6, 2024
fe74f58
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 9, 2024
3cd9fc5
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 9, 2024
a32bb35
tweak
havenbarnes Dec 9, 2024
3cb58ee
adjust feature management schema / migration
havenbarnes Dec 9, 2024
4c9e59e
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 9, 2024
2ed5491
rm unnecessary diffs
havenbarnes Dec 9, 2024
36b654d
rm unnecessary diffs
havenbarnes Dec 9, 2024
9887ea4
rm unnecessary diffs
havenbarnes Dec 9, 2024
6ec3092
Update query snapshots
github-actions[bot] Dec 9, 2024
4e4ce63
Update query snapshots
github-actions[bot] Dec 9, 2024
3e0f000
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 9, 2024
18a45ff
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 9, 2024
4adbf16
rm unnecessary diffs
havenbarnes Dec 9, 2024
c7fdde6
Update query snapshots
github-actions[bot] Dec 9, 2024
6a5bf26
Update query snapshots
github-actions[bot] Dec 9, 2024
6ca7b96
tweak
havenbarnes Dec 9, 2024
3db21f0
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 9, 2024
49d23d8
tweak
havenbarnes Dec 9, 2024
a1141c2
fix typecheck and tests
havenbarnes Dec 9, 2024
084a4f7
Merge branch 'master' into feature-management-backend-setup
havenbarnes Dec 10, 2024
cace516
fix typecheck and tests
havenbarnes Dec 10, 2024
0f7deeb
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 10, 2024
701eed7
Update query snapshots
github-actions[bot] Dec 10, 2024
202b419
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 17, 2024
c80640e
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 17, 2024
f242d4f
rework for v0 model
havenbarnes Dec 18, 2024
19d886e
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 18, 2024
5243896
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 18, 2024
64bc533
Update query snapshots
github-actions[bot] Dec 18, 2024
ca68d24
Update query snapshots
github-actions[bot] Dec 18, 2024
e7b07ef
tweak
havenbarnes Dec 18, 2024
ba8a5e6
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 18, 2024
ad6d336
remove unnecessary diff
havenbarnes Dec 18, 2024
8c8026c
Update query snapshots
github-actions[bot] Dec 18, 2024
a9792c3
tweak
havenbarnes Dec 18, 2024
cb0b4bb
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 18, 2024
2e721a6
Update query snapshots
github-actions[bot] Dec 18, 2024
8c70d49
tweak
havenbarnes Dec 18, 2024
5061056
tweak
havenbarnes Dec 18, 2024
20999b2
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 18, 2024
cfa0c4d
tweak
havenbarnes Dec 18, 2024
227295e
tweak
havenbarnes Dec 18, 2024
6fe434c
fix migration
havenbarnes Dec 18, 2024
374b9c5
tweak
havenbarnes Dec 18, 2024
9ac6bc6
Merge branch 'master' into feature-management-backend-setup
havenbarnes Dec 18, 2024
6964217
fix test
havenbarnes Dec 18, 2024
01959f1
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 18, 2024
8e6bb7f
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 18, 2024
3f1f88b
Update query snapshots
github-actions[bot] Dec 18, 2024
8e8b562
Update UI snapshots for `chromium` (1)
github-actions[bot] Dec 18, 2024
77a5a0c
Merge branch 'master' into feature-management-backend-setup
havenbarnes Dec 18, 2024
ee2635b
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 19, 2024
c10609f
tweak model fields
havenbarnes Dec 19, 2024
3c5fd20
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 19, 2024
6a675fe
tweak
havenbarnes Dec 19, 2024
a3fa2a7
Update UI snapshots for `chromium` (1)
github-actions[bot] Dec 19, 2024
cf0ff01
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
50ec2a1
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
9ad3981
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
349a0b5
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
87a626d
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
cf8f698
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
62f7e0d
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
42196f1
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
fcd9cc4
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
09970f6
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
275701d
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
b630896
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
251a049
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
a02d674
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
9de1f3e
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
6a66bbf
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
54e887f
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
43ab118
Update UI snapshots for `chromium` (2)
github-actions[bot] Dec 19, 2024
ce04bd8
stash
havenbarnes Dec 20, 2024
375bf83
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 20, 2024
9e988ee
fix linter
havenbarnes Dec 20, 2024
6d34dc2
Merge branch 'feature-management-backend-setup' of https://github.com…
havenbarnes Dec 20, 2024
5c2ba52
tweak
havenbarnes Dec 20, 2024
ec86c2f
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 20, 2024
d35989f
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Dec 30, 2024
db606bd
update
havenbarnes Dec 30, 2024
4a7d2bd
update
havenbarnes Dec 30, 2024
e4a67e1
tweak
havenbarnes Jan 3, 2025
796bfd5
tweak
havenbarnes Jan 3, 2025
adf602b
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Jan 3, 2025
3ee964b
Merge branch 'master' into feature-management-backend-setup
havenbarnes Jan 3, 2025
1ab5de5
delete dupe migration
havenbarnes Jan 3, 2025
5073dc6
Merge branch 'master' of https://github.com/PostHog/posthog into feat…
havenbarnes Jan 8, 2025
89a728e
update migrate script
havenbarnes Jan 8, 2025
dcfc9b1
remove field from serializer
havenbarnes Jan 8, 2025
f5fc480
remove field from serializer
havenbarnes Jan 8, 2025
46e68b1
Update query snapshots
github-actions[bot] Jan 8, 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: 7 additions & 0 deletions posthog/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
error_tracking,
event_definition,
exports,
feature,
feature_flag,
hog_function,
hog_function_template,
Expand Down Expand Up @@ -159,6 +160,12 @@ def register_grandfathered_environment_nested_viewset(
"project_activity_log",
["project_id"],
)
projects_router.register(
r"features",
feature.FeatureViewSet,
"project_feature_management",
["project_id"],
)
project_feature_flags_router = projects_router.register(
r"feature_flags",
feature_flag.FeatureFlagViewSet,
Expand Down
9 changes: 1 addition & 8 deletions posthog/api/early_access_feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,7 @@ class MinimalEarlyAccessFeatureSerializer(serializers.ModelSerializer):

class Meta:
model = EarlyAccessFeature
fields = [
"id",
"name",
"description",
"stage",
"documentationUrl",
"flagKey",
]
fields = ["id", "name", "description", "stage", "documentationUrl", "flagKey"]
read_only_fields = fields


Expand Down
111 changes: 111 additions & 0 deletions posthog/api/feature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from rest_framework import viewsets, serializers
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import QuerySet
from posthog.models import Feature
from posthog.api.routing import TeamAndOrgViewSetMixin
from posthog.api.forbid_destroy_model import ForbidDestroyModel
from posthog.rbac.access_control_api_mixin import AccessControlViewSetMixin


class FeatureSerializer(serializers.ModelSerializer):
class Meta:
model = Feature
fields = [
"id",
"name",
"description",
"documentation_url",
"issue_url",
"status",
"primary_feature_flag_id",
"created_at",
"updated_at",
"archived",
"deleted",
]

def create(self, validated_data):
validated_data["team_id"] = self.context["team_id"]
return super().create(validated_data)

def get_primary_feature_flag(self, feature: Feature):
from posthog.api.feature_flag import FeatureFlagSerializer

return FeatureFlagSerializer(feature.primary_feature_flag, context=self.context).data

def get_early_access_features(self, feature: Feature):
from posthog.api.early_access_feature import EarlyAccessFeatureSerializer

return EarlyAccessFeatureSerializer(feature.earlyaccessfeature_set, many=True).data

def get_experiments(self, feature: Feature):
from posthog.api.web_experiment import WebExperimentsAPISerializer

return WebExperimentsAPISerializer(feature.experiment_set, many=True).data

def get_feature_flags(self, feature: Feature):
from posthog.api.feature_flag import FeatureFlagSerializer

return FeatureFlagSerializer(feature.featureflag_set, context=self.context, many=True).data


class FeatureViewSet(TeamAndOrgViewSetMixin, AccessControlViewSetMixin, ForbidDestroyModel, viewsets.ModelViewSet):
scope_object = "feature"
queryset = Feature.objects.all()
serializer_class = FeatureSerializer

def safely_get_queryset(self, queryset) -> QuerySet:
# Base queryset with team filtering
queryset = Feature.objects.filter(team_id=self.team_id)

if self.action == "primary_feature_flag":
queryset = queryset.select_related("primary_feature_flag")
elif self.action == "experiments":
queryset = queryset.prefetch_related("experiment_set")
elif self.action == "early_access_features":
queryset = queryset.prefetch_related("earlyaccessfeature_set")
elif self.action == "feature_flags":
queryset = queryset.prefetch_related("featureflag_set")

return queryset

@action(detail=True, methods=["get"])
def primary_feature_flag(self, request, pk=None, **kwargs):
"""
Get primary feature flag associated with a specific feature.
"""
feature = self.get_object()
serializer = self.get_serializer(feature)
primary_feature_flag = serializer.get_primary_feature_flag(feature)
return Response(primary_feature_flag)

@action(detail=True, methods=["get"])
def feature_flags(self, request, pk=None, **kwargs):
"""
Get all feature flags associated with a specific feature.
"""
feature = self.get_object()
serializer = self.get_serializer(feature)
flags = serializer.get_feature_flags(feature)
return Response(flags)

@action(detail=True, methods=["get"])
def experiments(self, request, pk=None, **kwargs):
"""
Get experiments associated with a specific feature.
"""
feature = self.get_object()
serializer = self.get_serializer(feature)
experiments = serializer.get_experiments(feature)
return Response(experiments)

@action(detail=True, methods=["get"])
def early_access_features(self, request, pk=None, **kwargs):
"""
Get early access features associated with a specific feature.
"""
feature = self.get_object()
serializer = self.get_serializer(feature)
early_access_features = serializer.get_early_access_features(feature)
return Response(early_access_features)
204 changes: 204 additions & 0 deletions posthog/api/test/test_feature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
from rest_framework import status

from posthog.models import Feature, FeatureFlag, Experiment, EarlyAccessFeature, Team
from posthog.test.base import APIBaseTest


class TestFeatureAPI(APIBaseTest):
def setUp(self):
super().setUp()
self.feature = Feature.objects.create(

Check failure on line 10 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "status" for model "Feature"
team=self.team,
name="Test Feature",
description="Test Description",
documentation_url="http://example.com",
issue_url="http://github.com/example",
status="beta",
)

def test_list_features(self):
# Create a feature flag and experiment for the feature, ensure they are not returned in the response
Experiment.objects.create(

Check failure on line 21 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "Experiment"
team=self.team,
name="Test Experiment",
feature=self.feature,
feature_flag=FeatureFlag.objects.create(

Check failure on line 25 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "FeatureFlag"
team=self.team,
name="Test Flag for Experiment",
key="test-flag-for-experiment-list",
feature=self.feature,
),
)
EarlyAccessFeature.objects.create(

Check failure on line 32 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "EarlyAccessFeature"
team=self.team,
name="Test EAF",
description="Test Description",
feature=self.feature,
)

response = self.client.get(f"/api/projects/{self.team.id}/features/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.json()["results"]), 1)
self.assertEqual(response.json()["results"][0]["name"], "Test Feature")

# Ensure we are not returning joined data
with self.assertRaises(KeyError):
response.json()["results"][0]["experiments"]
with self.assertRaises(KeyError):
response.json()["results"][0]["feature_flags"]
with self.assertRaises(KeyError):
response.json()["results"][0]["early_access_features"]

def test_retrieve_feature(self):
Experiment.objects.create(

Check failure on line 53 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "Experiment"
team=self.team,
name="Test Experiment",
feature=self.feature,
feature_flag=FeatureFlag.objects.create(

Check failure on line 57 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "FeatureFlag"
team=self.team,
name="Test Flag for Experiment",
key="test-flag-for-experiment-retrieve",
feature=self.feature,
),
)
EarlyAccessFeature.objects.create(

Check failure on line 64 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "EarlyAccessFeature"
team=self.team,
name="Test EAF",
description="Test Description",
feature=self.feature,
)

response = self.client.get(f"/api/projects/{self.team.id}/features/{self.feature.id}/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["name"], "Test Feature")
self.assertEqual(response.json()["description"], "Test Description")

# Ensure we are not returning joined data
with self.assertRaises(KeyError):
response.json()["experiments"]
with self.assertRaises(KeyError):
response.json()["feature_flags"]
with self.assertRaises(KeyError):
response.json()["early_access_features"]

def test_create_feature(self):
response = self.client.post(
f"/api/projects/{self.team.id}/features/",
{
"name": "New Feature",
"team_id": self.team.id,
"description": "New Description",
"documentation_url": "http://example.com/new",
"issue_url": "http://github.com/example/new",
"status": "alpha",
},
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.json()["name"], "New Feature")
self.assertEqual(Feature.objects.count(), 2)

def test_update_feature(self):
response = self.client.patch(
f"/api/projects/{self.team.id}/features/{self.feature.id}/",
{
"name": "Updated Feature",
"status": "beta",
},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["name"], "Updated Feature")
self.assertEqual(response.json()["status"], "beta")

def test_delete_not_allowed(self):
response = self.client.delete(f"/api/projects/{self.team.id}/features/{self.feature.id}/")
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

def test_get_primary_feature_flag(self):
flag = FeatureFlag.objects.create(

Check failure on line 117 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "FeatureFlag"
team=self.team,
name="Test Flag",
key="test-flag",
feature=self.feature,
)
self.feature.primary_feature_flag = flag

Check failure on line 123 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

"Feature" has no attribute "primary_feature_flag"
self.feature.save()

response = self.client.get(f"/api/projects/{self.team.id}/features/{self.feature.id}/primary_feature_flag/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["key"], "test-flag")

def test_get_experiments(self):
Experiment.objects.create(

Check failure on line 131 in posthog/api/test/test_feature.py

View workflow job for this annotation

GitHub Actions / Python code quality checks

Unexpected attribute "feature" for model "Experiment"
team=self.team,
name="Test Experiment",
feature_flag=FeatureFlag.objects.create(
team=self.team,
name="Test Flag",
key="test-flag",
),
feature=self.feature,
description="Test Description",
)

response = self.client.get(f"/api/projects/{self.team.id}/features/{self.feature.id}/experiments/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]["name"], "Test Experiment")

def test_get_early_access_features(self):
EarlyAccessFeature.objects.create(
team=self.team,
name="Test EAF",
description="Test Description",
feature=self.feature,
)

response = self.client.get(f"/api/projects/{self.team.id}/features/{self.feature.id}/early_access_features/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]["name"], "Test EAF")

def test_get_feature_flags(self):
FeatureFlag.objects.create(
team=self.team,
name="Test Flag",
key="test-flag",
feature=self.feature,
)

response = self.client.get(f"/api/projects/{self.team.id}/features/{self.feature.id}/feature_flags/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.json()), 1)
self.assertEqual(response.json()[0]["key"], "test-flag")

def test_cannot_create_feature_without_name(self):
response = self.client.post(
f"/api/projects/{self.team.id}/features/",
{
"team": self.team.id,
"description": "New Description",
},
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("name", response.json()["attr"])

def test_cannot_access_feature_from_another_team(self):
other_team = Team.objects.create(
organization=self.organization,
api_token=self.CONFIG_API_TOKEN + "2",
test_account_filters=[
{
"key": "email",
"value": "@posthog.com",
"operator": "not_icontains",
"type": "person",
}
],
)
other_feature = Feature.objects.create(
team=other_team,
name="Other Feature",
)

response = self.client.get(f"/api/projects/{self.team.id}/features/{other_feature.id}/")
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
Loading
Loading