From c9c910df42c05398befaf3cd47d91f5e9d842673 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Mon, 3 May 2021 16:19:25 -0400 Subject: [PATCH 01/29] wip: support test_ api key --- posthog/api/capture.py | 8 ++++++ posthog/api/test/test_capture.py | 47 ++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index 3ea0e80ec65df..8b8af32f4a36d 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -166,6 +166,10 @@ def get_event(request): ), ) + # Support test_[apiKey] for users with multiple environments + is_test_environment = token.startswith("test_") + token = token[5:] if is_test_environment else token + team = Team.objects.get_team_from_token(token) if team is None: @@ -236,6 +240,10 @@ def get_event(request): if not event.get("properties"): event["properties"] = {} + # Support test_[apiKey] for users with multiple environments + if event["properties"].get("test_environment") is None: + event["properties"]["test_environment"] = True if is_test_environment else False + _ensure_web_feature_flags_in_properties(event, team, distinct_id) event_uuid = UUIDT() diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 66fc49537810b..9dff3cc406289 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -64,6 +64,7 @@ def test_capture_event(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], + "test_environment": False, }, } now = timezone.now() @@ -85,6 +86,40 @@ def test_capture_event(self, patch_process_event_with_plugins): }, ) + @patch("posthog.models.team.TEAM_CACHE", {}) + @patch("posthog.api.capture.celery_app.send_task") + def test_test_api_key(self, patch_process_event_with_plugins): + api_token = "test_" + self.team.api_token + data = { + "event": "$autocapture", + "properties": { + "distinct_id": 2, + "token": api_token, + "$elements": [ + {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, + {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, + ], + }, + } + now = timezone.now() + with freeze_time(now): + with self.assertNumQueries(2): + response = self.client.get("/e/?data=%s" % quote(self._to_json(data)), HTTP_ORIGIN="https://localhost",) + self.assertEqual(response.get("access-control-allow-origin"), "https://localhost") + arguments = self._to_arguments(patch_process_event_with_plugins) + arguments.pop("now") # can't compare fakedate + arguments.pop("sent_at") # can't compare fakedate + self.assertDictEqual( + arguments, + { + "distinct_id": "2", + "ip": "127.0.0.1", + "site_url": "http://testserver", + "data": {**data, "properties": {**data["properties"], "test_environment": True,}}, + "team_id": self.team.pk, + }, + ) + @patch("posthog.models.team.TEAM_CACHE", {}) @patch("posthog.api.capture.celery_app.send_task") def test_personal_api_key(self, patch_process_event_with_plugins): @@ -100,6 +135,7 @@ def test_personal_api_key(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], + "test_environment": False, }, } now = timezone.now() @@ -164,6 +200,7 @@ def test_personal_api_key_from_batch_request(self, patch_process_event_with_plug "$device_type": "Desktop", "distinct_id": "94b03e599131fd5026b", "token": "fake token", + "test_environment": False, }, "timestamp": "2021-04-20T19:11:33.841Z", }, @@ -326,7 +363,7 @@ def test_batch(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {}}, + "data": {**data, "properties": {"test_environment": False,}}, "team_id": self.team.pk, }, ) @@ -336,7 +373,7 @@ def test_batch(self, patch_process_event_with_plugins): def test_batch_gzip_header(self, patch_process_event_with_plugins): data = { "api_key": self.team.api_token, - "batch": [{"type": "capture", "event": "user signed up", "distinct_id": "2"}], + "batch": [{"type": "capture", "event": "user signed up", "distinct_id": "2",}], } response = self.client.generic( @@ -356,7 +393,7 @@ def test_batch_gzip_header(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {}}, + "data": {**data["batch"][0], "properties": {"test_environment": False,}}, "team_id": self.team.pk, }, ) @@ -385,7 +422,7 @@ def test_batch_gzip_param(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {}}, + "data": {**data["batch"][0], "properties": {"test_environment": False}}, "team_id": self.team.pk, }, ) @@ -415,7 +452,7 @@ def test_batch_lzstring(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {}}, + "data": {**data["batch"][0], "properties": {"test_environment": False,}}, "team_id": self.team.pk, }, ) From 4c832683afa351af559ecc7d13482e49fab48cd1 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 4 May 2021 13:55:14 -0400 Subject: [PATCH 02/29] Renamed test_environment property to --- posthog/api/capture.py | 4 ++-- posthog/api/test/test_capture.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index 8b8af32f4a36d..8977191a56eb2 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -241,8 +241,8 @@ def get_event(request): event["properties"] = {} # Support test_[apiKey] for users with multiple environments - if event["properties"].get("test_environment") is None: - event["properties"]["test_environment"] = True if is_test_environment else False + if event["properties"].get("$test_environment") is None: + event["properties"]["$test_environment"] = True if is_test_environment else False _ensure_web_feature_flags_in_properties(event, team, distinct_id) diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 9dff3cc406289..44c91bcec4533 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -64,7 +64,7 @@ def test_capture_event(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], - "test_environment": False, + "$test_environment": False, }, } now = timezone.now() @@ -115,7 +115,7 @@ def test_test_api_key(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {**data["properties"], "test_environment": True,}}, + "data": {**data, "properties": {**data["properties"], "$test_environment": True,}}, "team_id": self.team.pk, }, ) @@ -135,7 +135,7 @@ def test_personal_api_key(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], - "test_environment": False, + "$test_environment": False, }, } now = timezone.now() @@ -200,7 +200,7 @@ def test_personal_api_key_from_batch_request(self, patch_process_event_with_plug "$device_type": "Desktop", "distinct_id": "94b03e599131fd5026b", "token": "fake token", - "test_environment": False, + "$test_environment": False, }, "timestamp": "2021-04-20T19:11:33.841Z", }, @@ -363,7 +363,7 @@ def test_batch(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {"test_environment": False,}}, + "data": {**data, "properties": {"$test_environment": False,}}, "team_id": self.team.pk, }, ) @@ -393,7 +393,7 @@ def test_batch_gzip_header(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"test_environment": False,}}, + "data": {**data["batch"][0], "properties": {"$test_environment": False,}}, "team_id": self.team.pk, }, ) @@ -422,7 +422,7 @@ def test_batch_gzip_param(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"test_environment": False}}, + "data": {**data["batch"][0], "properties": {"$test_environment": False}}, "team_id": self.team.pk, }, ) @@ -452,7 +452,7 @@ def test_batch_lzstring(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"test_environment": False,}}, + "data": {**data["batch"][0], "properties": {"$test_environment": False,}}, "team_id": self.team.pk, }, ) From 55f7eff12a896eb9362ac4b6eb71b0e4e34ac3ce Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 4 May 2021 15:15:11 -0400 Subject: [PATCH 03/29] Added Prod/Test switch to determine which environment to show data for --- .../src/layout/navigation/TopNavigation.tsx | 19 +++++++++-- .../PropertyFilters/PropertyFilters.js | 34 +++++++++++-------- frontend/src/scenes/userLogic.tsx | 7 ++++ 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 986566bb88784..2c91aeefa45e3 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -7,7 +7,7 @@ import { userLogic } from 'scenes/userLogic' import { Badge } from 'lib/components/Badge' import { ChangelogModal } from '~/layout/ChangelogModal' import { router } from 'kea-router' -import { Button, Card, Dropdown, Tooltip } from 'antd' +import { Button, Card, Dropdown, Radio, Tooltip } from 'antd' import { ProjectOutlined, DownOutlined, @@ -78,10 +78,10 @@ export function TopNavigation(): JSX.Element { const { menuCollapsed, systemStatus, updateAvailable, changelogModalOpen, inviteMembersModalOpen } = useValues( navigationLogic ) - const { user } = useValues(userLogic) + const { user, productionEnvironment } = useValues(userLogic) const { preflight } = useValues(preflightLogic) const { billing } = useValues(billingLogic) - const { logout, updateCurrentTeam, updateCurrentOrganization } = useActions(userLogic) + const { logout, updateCurrentTeam, updateCurrentOrganization, setProductionEnvironment } = useActions(userLogic) const { showUpgradeModal } = useActions(sceneLogic) const { sceneConfig } = useValues(sceneLogic) const { push } = router.actions @@ -306,6 +306,19 @@ export function TopNavigation(): JSX.Element { {user?.team?.name} +
+ setProductionEnvironment(e.target.value)} + > + + PROD + + + TEST + + +
{user && (
diff --git a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js index 37750b2fda842..8b71bf8d70154 100644 --- a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js +++ b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js @@ -95,24 +95,28 @@ export function PropertyFilters({ const logic = propertyFilterLogic({ propertyFilters, endpoint, onChange, pageKey }) const { filters } = useValues(logic) + const hiddenFilters = ['test_environment'] + return (
{filters?.length && - filters.map((item, index) => { - return ( - - ) - })} + filters + .filter((item) => !hiddenFilters.includes(item.key)) + .map((item, index) => { + return ( + + ) + })}
) } diff --git a/frontend/src/scenes/userLogic.tsx b/frontend/src/scenes/userLogic.tsx index 38b39fc1c312a..8606803e99ebf 100644 --- a/frontend/src/scenes/userLogic.tsx +++ b/frontend/src/scenes/userLogic.tsx @@ -16,6 +16,7 @@ export const userLogic = kea>({ loadUser: (resetOnFailure?: boolean) => ({ resetOnFailure }), updateCurrentTeam: (teamId: number, destination?: string) => ({ teamId, destination }), updateCurrentOrganization: (organizationId: string, destination?: string) => ({ organizationId, destination }), + setProductionEnvironment: (isProduction: boolean) => ({ isProduction }), logout: true, }), reducers: { @@ -40,6 +41,12 @@ export const userLogic = kea>({ setUserLoading: (_, { loading }) => loading, }, ], + productionEnvironment: [ + true, + { + setProductionEnvironment: (_, payload) => payload.isProduction, + }, + ], }, selectors: ({ selectors }) => ({ demoOnlyProject: [ From 3bc0a0e818cdac8650603685408e9474269121ad Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 4 May 2021 15:38:11 -0400 Subject: [PATCH 04/29] moved environment toggle behind feature flag --- .../src/layout/navigation/TopNavigation.tsx | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 2c91aeefa45e3..aee3ac2e24a7f 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -33,6 +33,7 @@ import { CreateInviteModalWithButton } from 'scenes/organization/Settings/Create import MD5 from 'crypto-js/md5' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { billingLogic } from 'scenes/billing/billingLogic' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' export interface ProfilePictureProps { name?: string @@ -88,6 +89,7 @@ export function TopNavigation(): JSX.Element { const { showPalette } = useActions(commandPaletteLogic) const [projectModalShown, setProjectModalShown] = useState(false) // TODO: Move to Kea (using useState for backwards-compatibility with TopSelectors.tsx) const [organizationModalShown, setOrganizationModalShown] = useState(false) // TODO: Same as above + const { featureFlags } = useValues(featureFlagLogic) const whoAmIDropdown = (
@@ -306,19 +308,21 @@ export function TopNavigation(): JSX.Element { {user?.team?.name}
-
- setProductionEnvironment(e.target.value)} - > - - PROD - - - TEST - - -
+ {featureFlags['test-environment-3149'] && ( +
+ setProductionEnvironment(e.target.value)} + > + + PROD + + + TEST + + +
+ )}
{user && (
From 744f536dd872c97e7d3b4cbe00f8e4f990abeac9 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 4 May 2021 16:04:38 -0400 Subject: [PATCH 05/29] corrected key name to standard $ names --- frontend/src/lib/components/PropertyFilters/PropertyFilters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js index 8b71bf8d70154..c060de4201904 100644 --- a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js +++ b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js @@ -95,7 +95,7 @@ export function PropertyFilters({ const logic = propertyFilterLogic({ propertyFilters, endpoint, onChange, pageKey }) const { filters } = useValues(logic) - const hiddenFilters = ['test_environment'] + const hiddenFilters = ['$test_environment'] return (
From faaaf78abf50253f9a01b709bc1c9aa83df17f6a Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 4 May 2021 16:14:08 -0400 Subject: [PATCH 06/29] Moved hidden filters to PropertyKeyInfo for improved clarity --- .../src/lib/components/PropertyFilters/PropertyFilters.js | 4 ++-- frontend/src/lib/components/PropertyKeyInfo.tsx | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js index c060de4201904..13b516dfb8624 100644 --- a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js +++ b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js @@ -8,6 +8,8 @@ import { CloseButton } from 'lib/components/CloseButton' import PropertyFilterButton from './PropertyFilterButton' import '../../../scenes/actions/Actions.scss' +import { hiddenFilters } from 'lib/components/PropertyKeyInfo' + const FilterRow = React.memo(function FilterRow({ item, index, @@ -95,8 +97,6 @@ export function PropertyFilters({ const logic = propertyFilterLogic({ propertyFilters, endpoint, onChange, pageKey }) const { filters } = useValues(logic) - const hiddenFilters = ['$test_environment'] - return (
{filters?.length && diff --git a/frontend/src/lib/components/PropertyKeyInfo.tsx b/frontend/src/lib/components/PropertyKeyInfo.tsx index 203d665c24e6e..fdae000afcf17 100644 --- a/frontend/src/lib/components/PropertyKeyInfo.tsx +++ b/frontend/src/lib/components/PropertyKeyInfo.tsx @@ -433,6 +433,8 @@ export const keyMapping: KeyMappingInterface = { }, } +export const hiddenFilters: Array = ['$test_environment'] + interface PropertyKeyInfoInterface { value: string type?: 'event' | 'element' From 87018fca90cde75ea0f0466c7b7dd6346e1c5dfe Mon Sep 17 00:00:00 2001 From: Paolo D'Amico Date: Tue, 4 May 2021 20:01:33 -0700 Subject: [PATCH 07/29] fix typing --- posthog/api/test/test_capture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 44c91bcec4533..58cc84905fddd 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -90,7 +90,7 @@ def test_capture_event(self, patch_process_event_with_plugins): @patch("posthog.api.capture.celery_app.send_task") def test_test_api_key(self, patch_process_event_with_plugins): api_token = "test_" + self.team.api_token - data = { + data: Dict[str, Any] = { "event": "$autocapture", "properties": { "distinct_id": 2, @@ -115,7 +115,7 @@ def test_test_api_key(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {**data["properties"], "$test_environment": True,}}, + "data": {**data, "properties": {**data["properties"], "$test_environment": True}}, "team_id": self.team.pk, }, ) From b4bee837ee935ce2cfdf3da098b63aa7e2ba9876 Mon Sep 17 00:00:00 2001 From: Paolo D'Amico Date: Tue, 4 May 2021 20:39:08 -0700 Subject: [PATCH 08/29] proposed UI --- .../src/layout/navigation/Navigation.scss | 29 ++++++++++ .../src/layout/navigation/TopNavigation.tsx | 56 +++++++++++++------ 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/frontend/src/layout/navigation/Navigation.scss b/frontend/src/layout/navigation/Navigation.scss index 40865417e71c2..e3729ccc5f48e 100644 --- a/frontend/src/layout/navigation/Navigation.scss +++ b/frontend/src/layout/navigation/Navigation.scss @@ -283,6 +283,35 @@ height: 22px; } } + + .global-environment-switch { + margin-right: $default_spacing; + display: flex; + align-items: center; + label { + font-weight: bold; + color: $text_muted; + &:first-of-type { + padding-right: 4px; + &.active { + color: $warning; + } + } + &:last-of-type { + padding-left: 4px; + &.active { + color: $success; + } + } + } + .ant-switch:not(.ant-switch-checked) { + background-color: $warning; + } + + .ant-switch.ant-switch-checked { + background-color: $success; + } + } } .navigation-spacer { diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index aee3ac2e24a7f..df2fab0d66083 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -2,12 +2,12 @@ import React, { useState } from 'react' import './Navigation.scss' import { useActions, useValues } from 'kea' import { navigationLogic } from './navigationLogic' -import { IconBuilding, IconMenu } from 'lib/components/icons' +import { IconBuilding, IconExternalLink, IconMenu } from 'lib/components/icons' import { userLogic } from 'scenes/userLogic' import { Badge } from 'lib/components/Badge' import { ChangelogModal } from '~/layout/ChangelogModal' import { router } from 'kea-router' -import { Button, Card, Dropdown, Radio, Tooltip } from 'antd' +import { Button, Card, Dropdown, Switch, Tooltip } from 'antd' import { ProjectOutlined, DownOutlined, @@ -18,6 +18,8 @@ import { SettingOutlined, UserAddOutlined, InfoCircleOutlined, + ExperimentOutlined, + RocketOutlined, } from '@ant-design/icons' import { guardPremiumFeature } from 'scenes/UpgradeModal' import { sceneLogic } from 'scenes/sceneLogic' @@ -308,24 +310,44 @@ export function TopNavigation(): JSX.Element { {user?.team?.name}
- {featureFlags['test-environment-3149'] && ( -
- setProductionEnvironment(e.target.value)} - > - - PROD - - - TEST - - -
- )}
{user && (
+ {featureFlags['test-environment-3149'] && ( + + Toggle to view only test data everywhere.{' '} + + Click here + {' '} + to learn more. + + } + > +
+ + setProductionEnvironment(val)} + /> + +
+
+ )}
From ba0a6b1195ad53346ef4afa9c9d3706e653efa1e Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Wed, 5 May 2021 09:24:20 -0400 Subject: [PATCH 09/29] Renamed to ; Changed to a string and added environment const types: production, test; Moved into a hidden filter along with environment types for the frontend; Corrected tests to use environment constants; is no longer set by default but only when test_ is supplied in the apiKey or is manually supplied; Moved environment to navigationLogic; --- .../src/layout/navigation/TopNavigation.tsx | 30 ++++++++++------ .../src/layout/navigation/navigationLogic.ts | 8 +++++ .../PropertyFilters/PropertyFilters.js | 34 ++++++++----------- .../src/lib/components/PropertyKeyInfo.tsx | 11 +++++- frontend/src/scenes/userLogic.tsx | 7 ---- posthog/api/capture.py | 5 +-- posthog/api/test/test_capture.py | 14 ++++---- posthog/models/event.py | 2 ++ 8 files changed, 64 insertions(+), 47 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index df2fab0d66083..23bff30523d28 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -36,6 +36,7 @@ import MD5 from 'crypto-js/md5' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { billingLogic } from 'scenes/billing/billingLogic' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' +import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' export interface ProfilePictureProps { name?: string @@ -77,14 +78,21 @@ export function WhoAmI({ user }: { user: UserType }): JSX.Element { } export function TopNavigation(): JSX.Element { - const { setMenuCollapsed, setChangelogModalOpen, setInviteMembersModalOpen } = useActions(navigationLogic) - const { menuCollapsed, systemStatus, updateAvailable, changelogModalOpen, inviteMembersModalOpen } = useValues( + const { setMenuCollapsed, setChangelogModalOpen, setInviteMembersModalOpen, setFilteredEnvironment } = useActions( navigationLogic ) - const { user, productionEnvironment } = useValues(userLogic) + const { + menuCollapsed, + systemStatus, + updateAvailable, + changelogModalOpen, + inviteMembersModalOpen, + filteredEnvironment, + } = useValues(navigationLogic) + const { user } = useValues(userLogic) const { preflight } = useValues(preflightLogic) const { billing } = useValues(billingLogic) - const { logout, updateCurrentTeam, updateCurrentOrganization, setProductionEnvironment } = useActions(userLogic) + const { logout, updateCurrentTeam, updateCurrentOrganization } = useActions(userLogic) const { showUpgradeModal } = useActions(sceneLogic) const { sceneConfig } = useValues(sceneLogic) const { push } = router.actions @@ -317,7 +325,7 @@ export function TopNavigation(): JSX.Element { - Toggle to view only test data everywhere.{' '} + Toggle to view only test or production data everywhere.{' '} Click here {' '} @@ -328,20 +336,22 @@ export function TopNavigation(): JSX.Element {
setProductionEnvironment(val)} + value={filteredEnvironment === ENVIRONMENTS.PRODUCTION} + defaultChecked={filteredEnvironment === ENVIRONMENTS.PRODUCTION} + onChange={(val) => + setFilteredEnvironment(val ? ENVIRONMENTS.PRODUCTION : ENVIRONMENTS.TEST) + } /> diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index b3218e3fd15e3..ed2f1122f19e0 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -8,6 +8,7 @@ import { organizationLogic } from 'scenes/organizationLogic' import dayjs from 'dayjs' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' import { preflightLogic } from 'scenes/PreflightCheck/logic' +import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' type WarningType = | 'welcome' @@ -27,6 +28,7 @@ export const navigationLogic = kea ({ visible }), setInviteMembersModalOpen: (isOpen: boolean) => ({ isOpen }), setHotkeyNavigationEngaged: (hotkeyNavigationEngaged: boolean) => ({ hotkeyNavigationEngaged }), + setFilteredEnvironment: (environment: string) => ({ environment }), }, reducers: { menuCollapsed: [ @@ -65,6 +67,12 @@ export const navigationLogic = kea hotkeyNavigationEngaged, }, ], + filteredEnvironment: [ + ENVIRONMENTS.PRODUCTION, + { + setFilteredEnvironment: (_, payload) => payload.environment, + }, + ], }, selectors: { systemStatus: [ diff --git a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js index 13b516dfb8624..37750b2fda842 100644 --- a/frontend/src/lib/components/PropertyFilters/PropertyFilters.js +++ b/frontend/src/lib/components/PropertyFilters/PropertyFilters.js @@ -8,8 +8,6 @@ import { CloseButton } from 'lib/components/CloseButton' import PropertyFilterButton from './PropertyFilterButton' import '../../../scenes/actions/Actions.scss' -import { hiddenFilters } from 'lib/components/PropertyKeyInfo' - const FilterRow = React.memo(function FilterRow({ item, index, @@ -100,23 +98,21 @@ export function PropertyFilters({ return (
{filters?.length && - filters - .filter((item) => !hiddenFilters.includes(item.key)) - .map((item, index) => { - return ( - - ) - })} + filters.map((item, index) => { + return ( + + ) + })}
) } diff --git a/frontend/src/lib/components/PropertyKeyInfo.tsx b/frontend/src/lib/components/PropertyKeyInfo.tsx index fdae000afcf17..997de5483dad1 100644 --- a/frontend/src/lib/components/PropertyKeyInfo.tsx +++ b/frontend/src/lib/components/PropertyKeyInfo.tsx @@ -328,6 +328,12 @@ export const keyMapping: KeyMappingInterface = { examples: ['16ff262c4301e5-0aa346c03894bc-39667c0e-1aeaa0-16ff262c431767'], hide: true, }, + $environment: { + label: 'Environment', + description: 'Environment used to filter results on all queries when enabled.', + examples: ['test', 'production'], + hide: true, + }, // GeoIP $geoip_city_name: { @@ -433,7 +439,10 @@ export const keyMapping: KeyMappingInterface = { }, } -export const hiddenFilters: Array = ['$test_environment'] +export const ENVIRONMENTS = { + PRODUCTION: 'production', + TEST: 'test', +} interface PropertyKeyInfoInterface { value: string diff --git a/frontend/src/scenes/userLogic.tsx b/frontend/src/scenes/userLogic.tsx index 8606803e99ebf..38b39fc1c312a 100644 --- a/frontend/src/scenes/userLogic.tsx +++ b/frontend/src/scenes/userLogic.tsx @@ -16,7 +16,6 @@ export const userLogic = kea>({ loadUser: (resetOnFailure?: boolean) => ({ resetOnFailure }), updateCurrentTeam: (teamId: number, destination?: string) => ({ teamId, destination }), updateCurrentOrganization: (organizationId: string, destination?: string) => ({ organizationId, destination }), - setProductionEnvironment: (isProduction: boolean) => ({ isProduction }), logout: true, }), reducers: { @@ -41,12 +40,6 @@ export const userLogic = kea>({ setUserLoading: (_, { loading }) => loading, }, ], - productionEnvironment: [ - true, - { - setProductionEnvironment: (_, payload) => payload.isProduction, - }, - ], }, selectors: ({ selectors }) => ({ demoOnlyProject: [ diff --git a/posthog/api/capture.py b/posthog/api/capture.py index 8977191a56eb2..db47f8c16f0bf 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -17,6 +17,7 @@ from posthog.exceptions import RequestParsingError, generate_exception_response from posthog.helpers.session_recording import preprocess_session_recording_events from posthog.models import Team, User +from posthog.models.event import ENVIRONMENT_TEST from posthog.models.feature_flag import get_active_feature_flags from posthog.models.utils import UUIDT from posthog.utils import cors_response, get_ip_address, load_data_from_request @@ -241,8 +242,8 @@ def get_event(request): event["properties"] = {} # Support test_[apiKey] for users with multiple environments - if event["properties"].get("$test_environment") is None: - event["properties"]["$test_environment"] = True if is_test_environment else False + if event["properties"].get("$environment") is None and is_test_environment: + event["properties"]["$environment"] = ENVIRONMENT_TEST _ensure_web_feature_flags_in_properties(event, team, distinct_id) diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 58cc84905fddd..0bc426f1414e0 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -13,6 +13,7 @@ from rest_framework import status from posthog.models import PersonalAPIKey +from posthog.models.event import ENVIRONMENT_TEST from posthog.models.feature_flag import FeatureFlag from posthog.test.base import BaseTest @@ -64,7 +65,6 @@ def test_capture_event(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], - "$test_environment": False, }, } now = timezone.now() @@ -115,7 +115,7 @@ def test_test_api_key(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {**data["properties"], "$test_environment": True}}, + "data": {**data, "properties": {**data["properties"], "$environment": ENVIRONMENT_TEST}}, "team_id": self.team.pk, }, ) @@ -135,7 +135,6 @@ def test_personal_api_key(self, patch_process_event_with_plugins): {"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",}, {"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",}, ], - "$test_environment": False, }, } now = timezone.now() @@ -200,7 +199,6 @@ def test_personal_api_key_from_batch_request(self, patch_process_event_with_plug "$device_type": "Desktop", "distinct_id": "94b03e599131fd5026b", "token": "fake token", - "$test_environment": False, }, "timestamp": "2021-04-20T19:11:33.841Z", }, @@ -363,7 +361,7 @@ def test_batch(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data, "properties": {"$test_environment": False,}}, + "data": {**data, "properties": {}}, "team_id": self.team.pk, }, ) @@ -393,7 +391,7 @@ def test_batch_gzip_header(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"$test_environment": False,}}, + "data": {**data["batch"][0], "properties": {}}, "team_id": self.team.pk, }, ) @@ -422,7 +420,7 @@ def test_batch_gzip_param(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"$test_environment": False}}, + "data": {**data["batch"][0], "properties": {}}, "team_id": self.team.pk, }, ) @@ -452,7 +450,7 @@ def test_batch_lzstring(self, patch_process_event_with_plugins): "distinct_id": "2", "ip": "127.0.0.1", "site_url": "http://testserver", - "data": {**data["batch"][0], "properties": {"$test_environment": False,}}, + "data": {**data["batch"][0], "properties": {}}, "team_id": self.team.pk, }, ) diff --git a/posthog/models/event.py b/posthog/models/event.py index 798963a19ab50..1832c0da95b43 100644 --- a/posthog/models/event.py +++ b/posthog/models/event.py @@ -31,6 +31,8 @@ # TEAM_EVENT_ACTION_QUERY_CACHE looks like team_id -> event ex('$pageview') -> query TEAM_ACTION_QUERY_CACHE: Dict[int, str] = {} DEFAULT_EARLIEST_TIME_DELTA = relativedelta(weeks=1) +ENVIRONMENT_TEST = "test" +ENVIRONMENT_PRODUCTION = "production" class SelectorPart(object): From 1e3a56a757e5aab78bcf3079cbe1145536ac0eca Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Wed, 5 May 2021 09:33:00 -0400 Subject: [PATCH 10/29] Added filter for test environments so that when it's enabled all test environments are filtered out --- posthog/models/team.py | 1 + posthog/test/test_team.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/posthog/models/team.py b/posthog/models/team.py index 5e93c7b02aeec..5c4cbcd7e3afc 100644 --- a/posthog/models/team.py +++ b/posthog/models/team.py @@ -35,6 +35,7 @@ def set_test_account_filters(self, organization: Optional[Any]) -> List: "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, + {"key": "$environment", "operator": "is", "value": ["test"],}, ] if organization: example_emails = organization.members.only("email") diff --git a/posthog/test/test_team.py b/posthog/test/test_team.py index 53f7072898576..55ba4e8782045 100644 --- a/posthog/test/test_team.py +++ b/posthog/test/test_team.py @@ -25,6 +25,7 @@ def test_create_team_with_test_account_filters(self): "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, + {"key": "$environment", "operator": "is", "value": ["test"],}, ], ) @@ -41,6 +42,7 @@ def test_create_team_with_test_account_filters(self): "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, + {"key": "$environment", "operator": "is", "value": ["test"],}, ], ) From 3750ca3c4303af83bf2926bd6c45db86d43780e0 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Wed, 5 May 2021 09:59:54 -0400 Subject: [PATCH 11/29] Remove component if feature flag for test-environment is enabled --- frontend/src/scenes/insights/TestAccountFilter.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/scenes/insights/TestAccountFilter.tsx b/frontend/src/scenes/insights/TestAccountFilter.tsx index f3b57eb1bb8fb..b35881c671002 100644 --- a/frontend/src/scenes/insights/TestAccountFilter.tsx +++ b/frontend/src/scenes/insights/TestAccountFilter.tsx @@ -5,6 +5,7 @@ import React from 'react' import { FilterType } from '~/types' import { SettingOutlined } from '@ant-design/icons' import { teamLogic } from 'scenes/teamLogic' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' export function TestAccountFilter({ filters, @@ -15,8 +16,9 @@ export function TestAccountFilter({ }): JSX.Element | null { const { currentTeam } = useValues(teamLogic) const hasFilters = (currentTeam?.test_account_filters || []).length > 0 + const { featureFlags } = useValues(featureFlagLogic) - return ( + return featureFlags['test-environment-3149'] ? null : ( Date: Wed, 5 May 2021 17:35:53 -0700 Subject: [PATCH 12/29] adjust style of tooltip --- frontend/src/layout/navigation/TopNavigation.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 23bff30523d28..0dc63dec3b751 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -326,7 +326,12 @@ export function TopNavigation(): JSX.Element { title={ <> Toggle to view only test or production data everywhere.{' '} - + Click here {' '} to learn more. From 672c50c602ca9956de3c4d1f55edd010ed121ebe Mon Sep 17 00:00:00 2001 From: Paolo D'Amico Date: Wed, 5 May 2021 17:44:13 -0700 Subject: [PATCH 13/29] adjust UI based on @corywatilo's input --- .../src/layout/navigation/Navigation.scss | 22 +++---- .../src/layout/navigation/TopNavigation.tsx | 66 +++++++------------ 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/frontend/src/layout/navigation/Navigation.scss b/frontend/src/layout/navigation/Navigation.scss index e3729ccc5f48e..68b73c1dd3bc7 100644 --- a/frontend/src/layout/navigation/Navigation.scss +++ b/frontend/src/layout/navigation/Navigation.scss @@ -290,18 +290,18 @@ align-items: center; label { font-weight: bold; - color: $text_muted; - &:first-of-type { - padding-right: 4px; - &.active { - color: $warning; - } + color: $success; + padding-right: 4px; + a { + color: $text_muted; } - &:last-of-type { - padding-left: 4px; - &.active { - color: $success; - } + + svg { + margin-right: 4px; + } + + &.test { + color: $warning; } } .ant-switch:not(.ant-switch-checked) { diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 0dc63dec3b751..c74421a08f966 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import './Navigation.scss' import { useActions, useValues } from 'kea' import { navigationLogic } from './navigationLogic' -import { IconBuilding, IconExternalLink, IconMenu } from 'lib/components/icons' +import { IconBuilding, IconMenu } from 'lib/components/icons' import { userLogic } from 'scenes/userLogic' import { Badge } from 'lib/components/Badge' import { ChangelogModal } from '~/layout/ChangelogModal' @@ -18,8 +18,6 @@ import { SettingOutlined, UserAddOutlined, InfoCircleOutlined, - ExperimentOutlined, - RocketOutlined, } from '@ant-design/icons' import { guardPremiumFeature } from 'scenes/UpgradeModal' import { sceneLogic } from 'scenes/sceneLogic' @@ -322,46 +320,28 @@ export function TopNavigation(): JSX.Element { {user && (
{featureFlags['test-environment-3149'] && ( - - Toggle to view only test or production data everywhere.{' '} - - Click here - {' '} - to learn more. - - } - > -
- - - setFilteredEnvironment(val ? ENVIRONMENTS.PRODUCTION : ENVIRONMENTS.TEST) - } - /> - -
-
+
+ + + setFilteredEnvironment(val ? ENVIRONMENTS.PRODUCTION : ENVIRONMENTS.TEST) + } + /> +
)}
From ac00ccaf9ef20432e991b7bac8803362097b2c8d Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Thu, 6 May 2021 16:44:44 -0400 Subject: [PATCH 14/29] implemented toggle functionality --- .../src/layout/navigation/navigationLogic.ts | 26 ++++++++- frontend/src/lib/api.js | 55 ++++++++++++++++++- frontend/src/lib/constants.tsx | 2 + frontend/src/lib/utils.tsx | 10 +++- posthog/models/team.py | 3 +- 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index ed2f1122f19e0..7c8ecd0f53791 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -9,6 +9,8 @@ import dayjs from 'dayjs' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' +import { ENVIRONMENT_LOCAL_STORAGE_KEY } from 'lib/constants' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' type WarningType = | 'welcome' @@ -28,7 +30,7 @@ export const navigationLogic = kea ({ visible }), setInviteMembersModalOpen: (isOpen: boolean) => ({ isOpen }), setHotkeyNavigationEngaged: (hotkeyNavigationEngaged: boolean) => ({ hotkeyNavigationEngaged }), - setFilteredEnvironment: (environment: string) => ({ environment }), + setFilteredEnvironment: (environment: string, pageload: boolean = false) => ({ environment, pageload }), }, reducers: { menuCollapsed: [ @@ -70,7 +72,9 @@ export const navigationLogic = kea payload.environment, + setFilteredEnvironment: (_, payload) => { + return payload.environment + }, }, ], }, @@ -170,9 +174,27 @@ export const navigationLogic = kea { + const localStorageValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) + const isLocalStorageValueEmpty = localStorageValue === null + const shouldWriteToLocalStorage = + (payload.pageload === true && isLocalStorageValueEmpty) || payload.pageload === false + if (shouldWriteToLocalStorage) { + window.localStorage.setItem(ENVIRONMENT_LOCAL_STORAGE_KEY, payload.environment) + } + const shouldReload = payload.pageload === false && localStorageValue !== payload.environment + if (shouldReload) { + location.reload() + } + }, }), events: ({ actions }) => ({ afterMount: () => { + if (featureFlagLogic.values.featureFlags['test-environment-3149']) { + const localStorageValue = + window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) || ENVIRONMENTS.PRODUCTION + actions.setFilteredEnvironment(localStorageValue, true) + } actions.loadLatestVersion() }, }), diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index 14adaee22fa5c..1d72d37ee3d0f 100644 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -1,3 +1,7 @@ +import { fromParamsGivenUrl, toParams } from 'lib/utils' +import { ENVIRONMENT_LOCAL_STORAGE_KEY } from 'lib/constants' +import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' + export function getCookie(name) { var cookieValue = null if (document.cookie && document.cookie !== '') { @@ -24,9 +28,8 @@ async function getJSONOrThrow(response) { class Api { async get(url) { - if (url.indexOf('http') !== 0) { - url = '/' + url + (url.indexOf('?') === -1 && url[url.length - 1] !== '/' ? '/' : '') - } + // TODO: how to put behind a feature flag + url = maybeAddEnvironmentProperty(url) let response try { @@ -103,5 +106,51 @@ class Api { return response } } + +function isWhitelisted(url) { + const WHITELIST = ['api'] + + for (let i = 0; i < WHITELIST.length; i++) { + let startsWith = url.indexOf(WHITELIST[i]) === 0 + let startsWithSlash = '/' + url.indexOf(WHITELIST[i]) === 0 + if (startsWith || startsWithSlash) { + return true + } + } + + return false +} + +function maybeAddEnvironmentProperty(url) { + const localStorageEnvironmentValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) + const shouldAddEnvironmentValue = + localStorageEnvironmentValue && isWhitelisted(url) && localStorageEnvironmentValue === ENVIRONMENTS.TEST + + if (shouldAddEnvironmentValue) { + let urlObject = url.indexOf('http') === 0 ? new URL(url) : new URL(url, window.location.origin) + + let params = fromParamsGivenUrl(urlObject.search) + + const environmentProperty = + localStorageEnvironmentValue === ENVIRONMENTS.PRODUCTION + ? { key: '$environment', operator: 'is_not', value: ['test'] } + : { key: '$environment', operator: 'exact', value: ['test'] } + + if (params.properties) { + let parsedProperties = JSON.parse(params.properties) + parsedProperties.push(environmentProperty) + params.properties = JSON.stringify(parsedProperties) + } else { + params.properties = JSON.stringify([environmentProperty]) + } + + return url.indexOf('http') === 0 + ? urlObject.origin + urlObject.pathname + '?' + toParams(params) + : urlObject.pathname + '?' + toParams(params) + } else if (url.indexOf('http') !== 0) { + return '/' + url + (url.indexOf('?') === -1 && url[url.length - 1] !== '/' ? '/' : '') + } +} + let api = new Api() export default api diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 59b70d4b2e3d3..69f99f91e1009 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -228,3 +228,5 @@ export const FEATURE_FLAGS: Record = { INGESTION_GRID: 'ingestion-grid-exp-3', PROJECT_HOME: 'project-home-exp-5', } + +export const ENVIRONMENT_LOCAL_STORAGE_KEY = '$environment' diff --git a/frontend/src/lib/utils.tsx b/frontend/src/lib/utils.tsx index 7b04d8fa0df7b..c8434fd8f0941 100644 --- a/frontend/src/lib/utils.tsx +++ b/frontend/src/lib/utils.tsx @@ -43,10 +43,10 @@ export function toParams(obj: Record): string { .join('&') } -export function fromParams(): Record { - return !window.location.search +export function fromParamsGivenUrl(url: string): Record { + return !url ? {} - : window.location.search + : url .slice(1) .split('&') .reduce((paramsObject, paramString) => { @@ -56,6 +56,10 @@ export function fromParams(): Record { }, {} as Record) } +export function fromParams(): Record { + return fromParamsGivenUrl(window.location.search) +} + export function percentage(division: number): string { return division ? division.toLocaleString(undefined, { diff --git a/posthog/models/team.py b/posthog/models/team.py index 5c4cbcd7e3afc..6c379d4364fa9 100644 --- a/posthog/models/team.py +++ b/posthog/models/team.py @@ -35,7 +35,8 @@ def set_test_account_filters(self, organization: Optional[Any]) -> List: "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, - {"key": "$environment", "operator": "is", "value": ["test"],}, + {"key": "$environment", "operator": "exact", "value": ["test"],}, + # {"key": "$environment", "operator": "is_not_set", }, ] if organization: example_emails = organization.members.only("email") From 0d704062b08fce0b2010a750690bae5bea3753b0 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Fri, 7 May 2021 07:35:09 -0400 Subject: [PATCH 15/29] Made Environments an enum for clarity --- frontend/src/layout/navigation/TopNavigation.tsx | 12 ++++++------ frontend/src/layout/navigation/navigationLogic.ts | 6 +++--- frontend/src/lib/api.js | 6 +++--- frontend/src/lib/components/PropertyKeyInfo.tsx | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index c74421a08f966..112f9139c0645 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -34,7 +34,7 @@ import MD5 from 'crypto-js/md5' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { billingLogic } from 'scenes/billing/billingLogic' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' +import { Environments } from 'lib/components/PropertyKeyInfo' export interface ProfilePictureProps { name?: string @@ -323,22 +323,22 @@ export function TopNavigation(): JSX.Element {
- setFilteredEnvironment(val ? ENVIRONMENTS.PRODUCTION : ENVIRONMENTS.TEST) + setFilteredEnvironment(val ? Environments.PRODUCTION : Environments.TEST) } />
diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index 7c8ecd0f53791..6a25fe5b446e9 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -8,7 +8,7 @@ import { organizationLogic } from 'scenes/organizationLogic' import dayjs from 'dayjs' import { eventUsageLogic } from 'lib/utils/eventUsageLogic' import { preflightLogic } from 'scenes/PreflightCheck/logic' -import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' +import { Environments } from 'lib/components/PropertyKeyInfo' import { ENVIRONMENT_LOCAL_STORAGE_KEY } from 'lib/constants' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' @@ -70,7 +70,7 @@ export const navigationLogic = kea { return payload.environment @@ -192,7 +192,7 @@ export const navigationLogic = kea { if (featureFlagLogic.values.featureFlags['test-environment-3149']) { const localStorageValue = - window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) || ENVIRONMENTS.PRODUCTION + window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) || Environments.PRODUCTION actions.setFilteredEnvironment(localStorageValue, true) } actions.loadLatestVersion() diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index 1d72d37ee3d0f..146edaa524d3c 100644 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -1,6 +1,6 @@ import { fromParamsGivenUrl, toParams } from 'lib/utils' import { ENVIRONMENT_LOCAL_STORAGE_KEY } from 'lib/constants' -import { ENVIRONMENTS } from 'lib/components/PropertyKeyInfo' +import { Environments } from 'lib/components/PropertyKeyInfo' export function getCookie(name) { var cookieValue = null @@ -124,7 +124,7 @@ function isWhitelisted(url) { function maybeAddEnvironmentProperty(url) { const localStorageEnvironmentValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) const shouldAddEnvironmentValue = - localStorageEnvironmentValue && isWhitelisted(url) && localStorageEnvironmentValue === ENVIRONMENTS.TEST + localStorageEnvironmentValue && isWhitelisted(url) && localStorageEnvironmentValue === Environments.TEST if (shouldAddEnvironmentValue) { let urlObject = url.indexOf('http') === 0 ? new URL(url) : new URL(url, window.location.origin) @@ -132,7 +132,7 @@ function maybeAddEnvironmentProperty(url) { let params = fromParamsGivenUrl(urlObject.search) const environmentProperty = - localStorageEnvironmentValue === ENVIRONMENTS.PRODUCTION + localStorageEnvironmentValue === Environments.PRODUCTION ? { key: '$environment', operator: 'is_not', value: ['test'] } : { key: '$environment', operator: 'exact', value: ['test'] } diff --git a/frontend/src/lib/components/PropertyKeyInfo.tsx b/frontend/src/lib/components/PropertyKeyInfo.tsx index 997de5483dad1..818f9f5e8f6ad 100644 --- a/frontend/src/lib/components/PropertyKeyInfo.tsx +++ b/frontend/src/lib/components/PropertyKeyInfo.tsx @@ -439,9 +439,9 @@ export const keyMapping: KeyMappingInterface = { }, } -export const ENVIRONMENTS = { - PRODUCTION: 'production', - TEST: 'test', +export enum Environments { + PRODUCTION = 'production', + TEST = 'test', } interface PropertyKeyInfoInterface { From 1de0325f8c5c46a625e8ebd963ef9f1160c3f1fa Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Fri, 7 May 2021 07:38:55 -0400 Subject: [PATCH 16/29] Moved environment constants to constants.py for consistency --- posthog/api/capture.py | 2 +- posthog/api/test/test_capture.py | 2 +- posthog/constants.py | 3 +++ posthog/models/event.py | 2 -- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index db47f8c16f0bf..834814507f65f 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -13,11 +13,11 @@ from sentry_sdk import capture_exception from posthog.celery import app as celery_app +from posthog.constants import ENVIRONMENT_TEST from posthog.ee import is_ee_enabled from posthog.exceptions import RequestParsingError, generate_exception_response from posthog.helpers.session_recording import preprocess_session_recording_events from posthog.models import Team, User -from posthog.models.event import ENVIRONMENT_TEST from posthog.models.feature_flag import get_active_feature_flags from posthog.models.utils import UUIDT from posthog.utils import cors_response, get_ip_address, load_data_from_request diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 0bc426f1414e0..00842c20a1813 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -12,8 +12,8 @@ from freezegun import freeze_time from rest_framework import status +from posthog.constants import ENVIRONMENT_TEST from posthog.models import PersonalAPIKey -from posthog.models.event import ENVIRONMENT_TEST from posthog.models.feature_flag import FeatureFlag from posthog.test.base import BaseTest diff --git a/posthog/constants.py b/posthog/constants.py index ddb7afce167f2..10039821ee8d0 100644 --- a/posthog/constants.py +++ b/posthog/constants.py @@ -99,3 +99,6 @@ class RDBMS(str, Enum): WEEKLY_ACTIVE = "weekly_active" MONTHLY_ACTIVE = "monthly_active" + +ENVIRONMENT_TEST = "test" +ENVIRONMENT_PRODUCTION = "production" diff --git a/posthog/models/event.py b/posthog/models/event.py index 1832c0da95b43..798963a19ab50 100644 --- a/posthog/models/event.py +++ b/posthog/models/event.py @@ -31,8 +31,6 @@ # TEAM_EVENT_ACTION_QUERY_CACHE looks like team_id -> event ex('$pageview') -> query TEAM_ACTION_QUERY_CACHE: Dict[int, str] = {} DEFAULT_EARLIEST_TIME_DELTA = relativedelta(weeks=1) -ENVIRONMENT_TEST = "test" -ENVIRONMENT_PRODUCTION = "production" class SelectorPart(object): From 0268bed7b9f85de94b580312ba50186dc3281076 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Fri, 7 May 2021 07:45:34 -0400 Subject: [PATCH 17/29] Moved Environments into constants for consistency --- frontend/src/layout/navigation/TopNavigation.tsx | 4 ++-- frontend/src/layout/navigation/navigationLogic.ts | 3 +-- frontend/src/lib/api.js | 3 +-- frontend/src/lib/components/PropertyKeyInfo.tsx | 5 ----- frontend/src/lib/constants.tsx | 5 +++++ 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 112f9139c0645..8e607e8aa8cbb 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -34,7 +34,7 @@ import MD5 from 'crypto-js/md5' import { preflightLogic } from 'scenes/PreflightCheck/logic' import { billingLogic } from 'scenes/billing/billingLogic' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import { Environments } from 'lib/components/PropertyKeyInfo' +import { Environments } from 'lib/constants' export interface ProfilePictureProps { name?: string @@ -330,7 +330,7 @@ export function TopNavigation(): JSX.Element { - {filteredEnvironment === Environments.PRODUCTION ? 'Live' : 'Test'} + {filteredEnvironment === Environments.PRODUCTION ? 'Production' : 'Test'} = { } export const ENVIRONMENT_LOCAL_STORAGE_KEY = '$environment' + +export enum Environments { + PRODUCTION = 'production', + TEST = 'test', +} From 6f1f1687571469232d80ab929da93d1c5d6b6767 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Fri, 7 May 2021 07:50:44 -0400 Subject: [PATCH 18/29] Using parameter destructuring for better syntax --- frontend/src/layout/navigation/navigationLogic.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index b6e90cfadd468..73ebd95620c13 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -29,7 +29,7 @@ export const navigationLogic = kea ({ visible }), setInviteMembersModalOpen: (isOpen: boolean) => ({ isOpen }), setHotkeyNavigationEngaged: (hotkeyNavigationEngaged: boolean) => ({ hotkeyNavigationEngaged }), - setFilteredEnvironment: (environment: string, pageload: boolean = false) => ({ environment, pageload }), + setFilteredEnvironment: (environment: string, pageLoad: boolean = false) => ({ environment, pageLoad }), }, reducers: { menuCollapsed: [ @@ -71,9 +71,7 @@ export const navigationLogic = kea { - return payload.environment - }, + setFilteredEnvironment: (_, { environment }) => environment, }, ], }, @@ -173,15 +171,14 @@ export const navigationLogic = kea { + setFilteredEnvironment: ({ pageLoad, environment }) => { const localStorageValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) const isLocalStorageValueEmpty = localStorageValue === null - const shouldWriteToLocalStorage = - (payload.pageload === true && isLocalStorageValueEmpty) || payload.pageload === false + const shouldWriteToLocalStorage = (pageLoad === true && isLocalStorageValueEmpty) || pageLoad === false if (shouldWriteToLocalStorage) { - window.localStorage.setItem(ENVIRONMENT_LOCAL_STORAGE_KEY, payload.environment) + window.localStorage.setItem(ENVIRONMENT_LOCAL_STORAGE_KEY, environment) } - const shouldReload = payload.pageload === false && localStorageValue !== payload.environment + const shouldReload = pageLoad === false && localStorageValue !== environment if (shouldReload) { location.reload() } From b7e91e8d02f30e24e32196bfef055f8756c2f39c Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Fri, 7 May 2021 08:28:23 -0400 Subject: [PATCH 19/29] Make sure type is set as a string --- frontend/src/layout/navigation/navigationLogic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index 73ebd95620c13..fd07785d44473 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -69,7 +69,7 @@ export const navigationLogic = kea environment, }, From db993cc0a6cc3349bf56c6f174a0b4424c9577db Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Sat, 8 May 2021 07:35:15 -0400 Subject: [PATCH 20/29] Removed test filters --- posthog/models/team.py | 2 -- posthog/test/test_team.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/posthog/models/team.py b/posthog/models/team.py index 6c379d4364fa9..5e93c7b02aeec 100644 --- a/posthog/models/team.py +++ b/posthog/models/team.py @@ -35,8 +35,6 @@ def set_test_account_filters(self, organization: Optional[Any]) -> List: "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, - {"key": "$environment", "operator": "exact", "value": ["test"],}, - # {"key": "$environment", "operator": "is_not_set", }, ] if organization: example_emails = organization.members.only("email") diff --git a/posthog/test/test_team.py b/posthog/test/test_team.py index 9bf1f5d5f79b7..bd322f69b0edf 100644 --- a/posthog/test/test_team.py +++ b/posthog/test/test_team.py @@ -28,7 +28,6 @@ def test_create_team_with_test_account_filters(self): "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, - {"key": "$environment", "operator": "is", "value": ["test"],}, ], ) @@ -45,7 +44,6 @@ def test_create_team_with_test_account_filters(self): "operator": "is_not", "value": ["localhost:8000", "localhost:5000", "127.0.0.1:8000", "127.0.0.1:3000", "localhost:3000"], }, - {"key": "$environment", "operator": "is", "value": ["test"],}, ], ) From ed0caa74c8bfb10e2ad2cda44f4050ed5115b7c0 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Mon, 10 May 2021 08:09:57 -0400 Subject: [PATCH 21/29] Created _clean_token to ensure test_ is removed from all the places --- posthog/api/capture.py | 11 ++++++++--- posthog/api/decide.py | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index 834814507f65f..7ff3384c204a6 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -103,6 +103,13 @@ def _get_token(data, request) -> Optional[str]: return None +# Support test_[apiKey] for users with multiple environments +def _clean_token(token): + is_test_environment = token.startswith("test_") + token = token[5:] if is_test_environment else token + return (token, is_test_environment) + + def _get_project_id(data, request) -> Optional[int]: if request.GET.get("project_id"): return int(request.POST["project_id"]) @@ -167,9 +174,7 @@ def get_event(request): ), ) - # Support test_[apiKey] for users with multiple environments - is_test_environment = token.startswith("test_") - token = token[5:] if is_test_environment else token + token, is_test_environment = _clean_token(token) team = Team.objects.get_team_from_token(token) diff --git a/posthog/api/decide.py b/posthog/api/decide.py index b372e85e63585..863736bbf512d 100644 --- a/posthog/api/decide.py +++ b/posthog/api/decide.py @@ -13,7 +13,7 @@ from posthog.models.feature_flag import get_active_feature_flags from posthog.utils import cors_response, load_data_from_request -from .capture import _get_project_id, _get_token +from .capture import _clean_token, _get_project_id, _get_token def on_permitted_domain(team: Team, request: HttpRequest) -> bool: @@ -87,6 +87,7 @@ def get_decide(request: HttpRequest): request, generate_exception_response(f"Malformed request data: {error}", code="malformed_data"), ) token = _get_token(data, request) + token, is_test_environment = _clean_token(token) team = Team.objects.get_team_from_token(token) if team is None and token: project_id = _get_project_id(data, request) From 6da97abf05579de93e31e309867470ac5d997089 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Mon, 10 May 2021 08:44:19 -0400 Subject: [PATCH 22/29] Bug fixes for adding filter property so that it work properly --- frontend/src/layout/navigation/TopNavigation.tsx | 2 +- frontend/src/lib/api.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/src/layout/navigation/TopNavigation.tsx b/frontend/src/layout/navigation/TopNavigation.tsx index 8e607e8aa8cbb..3f71d35617765 100644 --- a/frontend/src/layout/navigation/TopNavigation.tsx +++ b/frontend/src/layout/navigation/TopNavigation.tsx @@ -335,7 +335,7 @@ export function TopNavigation(): JSX.Element { setFilteredEnvironment(val ? Environments.PRODUCTION : Environments.TEST) diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index 8441fa921ec12..b53178ec252e0 100644 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -110,9 +110,9 @@ function isWhitelisted(url) { const WHITELIST = ['api'] for (let i = 0; i < WHITELIST.length; i++) { - let startsWith = url.indexOf(WHITELIST[i]) === 0 - let startsWithSlash = '/' + url.indexOf(WHITELIST[i]) === 0 - if (startsWith || startsWithSlash) { + const urlWithSlash = '/' + url + const startsWith = url.indexOf(WHITELIST[i]) === 0 || urlWithSlash.indexOf(WHITELIST[i]) === 0 + if (startsWith) { return true } } @@ -122,8 +122,8 @@ function isWhitelisted(url) { function maybeAddEnvironmentProperty(url) { const localStorageEnvironmentValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) - const shouldAddEnvironmentValue = - localStorageEnvironmentValue && isWhitelisted(url) && localStorageEnvironmentValue === Environments.TEST + const isWhitelistedUrl = isWhitelisted(url) + const shouldAddEnvironmentValue = localStorageEnvironmentValue && isWhitelistedUrl if (shouldAddEnvironmentValue) { let urlObject = url.indexOf('http') === 0 ? new URL(url) : new URL(url, window.location.origin) @@ -137,7 +137,9 @@ function maybeAddEnvironmentProperty(url) { if (params.properties) { let parsedProperties = JSON.parse(params.properties) - parsedProperties.push(environmentProperty) + parsedProperties = Array.isArray(parsedProperties) + ? [...parsedProperties, environmentProperty] + : [parsedProperties, environmentProperty] params.properties = JSON.stringify(parsedProperties) } else { params.properties = JSON.stringify([environmentProperty]) From f5ef02570f8fa986caee5f47fee9ad3c1f863de3 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Mon, 10 May 2021 08:52:00 -0400 Subject: [PATCH 23/29] Show test account filter --- .../insights/TestAccountFilter/TestAccountFilter.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/scenes/insights/TestAccountFilter/TestAccountFilter.tsx b/frontend/src/scenes/insights/TestAccountFilter/TestAccountFilter.tsx index b35881c671002..5fb6e7fdd70e1 100644 --- a/frontend/src/scenes/insights/TestAccountFilter/TestAccountFilter.tsx +++ b/frontend/src/scenes/insights/TestAccountFilter/TestAccountFilter.tsx @@ -5,7 +5,7 @@ import React from 'react' import { FilterType } from '~/types' import { SettingOutlined } from '@ant-design/icons' import { teamLogic } from 'scenes/teamLogic' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' +//import { featureFlagLogic } from 'lib/logic/featureFlagLogic' export function TestAccountFilter({ filters, @@ -16,9 +16,10 @@ export function TestAccountFilter({ }): JSX.Element | null { const { currentTeam } = useValues(teamLogic) const hasFilters = (currentTeam?.test_account_filters || []).length > 0 - const { featureFlags } = useValues(featureFlagLogic) + //const { featureFlags } = useValues(featureFlagLogic) - return featureFlags['test-environment-3149'] ? null : ( + //return featureFlags['test-environment-3149'] ? null : ( + return ( Date: Mon, 10 May 2021 09:25:29 -0400 Subject: [PATCH 24/29] ensure token isn't None so that mypy checks pass --- posthog/api/capture.py | 1 + 1 file changed, 1 insertion(+) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index d8dd56d6837c5..ff37c00b74a29 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -177,6 +177,7 @@ def get_event(request): ) token, is_test_environment = _clean_token(token) + assert token is not None team = Team.objects.get_team_from_token(token) From bd129c6af9a1b14da0ea865ec6642c42f267e9db Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 11 May 2021 10:01:25 -0400 Subject: [PATCH 25/29] Corrected css selector syntax --- cypress/integration/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/dashboard.js b/cypress/integration/dashboard.js index eb74044ba054b..a4af6da7558db 100644 --- a/cypress/integration/dashboard.js +++ b/cypress/integration/dashboard.js @@ -37,7 +37,7 @@ describe('Dashboard', () => { .then((link) => { cy.wait(200) cy.visit(link) - cy.get('[data-attr="dashboard-item-title"').should('contain', 'Daily Active Users') + cy.get('[data-attr="dashboard-item-title"]').should('contain', 'Daily Active Users') }) }) From 616cbd3247030a5c77f6b90fd9e4d989755a40db Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 11 May 2021 11:46:31 -0400 Subject: [PATCH 26/29] removed quote since it's not needed --- cypress/integration/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/dashboard.js b/cypress/integration/dashboard.js index 08f6db4210ff5..087ed04d1a872 100644 --- a/cypress/integration/dashboard.js +++ b/cypress/integration/dashboard.js @@ -37,7 +37,7 @@ describe('Dashboard', () => { .then((link) => { cy.wait(200) cy.visit(link) - cy.get('[data-attr="dashboard-item-title"]').should('contain', 'Daily Active Users') + cy.get('[data-attr=dashboard-item-title]').should('contain', 'Daily Active Users') }) }) From faf89fea016dbb44b1e7981486b7645a60a9522e Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Tue, 11 May 2021 14:04:19 -0400 Subject: [PATCH 27/29] Corrected cypress test by excluding featureFlag usage on shared dashboard scene --- frontend/src/layout/navigation/navigationLogic.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/layout/navigation/navigationLogic.ts b/frontend/src/layout/navigation/navigationLogic.ts index fd07785d44473..66593933cfd03 100644 --- a/frontend/src/layout/navigation/navigationLogic.ts +++ b/frontend/src/layout/navigation/navigationLogic.ts @@ -186,7 +186,8 @@ export const navigationLogic = kea ({ afterMount: () => { - if (featureFlagLogic.values.featureFlags['test-environment-3149']) { + const notSharedDashboard = location.pathname.indexOf('shared_dashboard') > -1 ? false : true + if (notSharedDashboard && featureFlagLogic.values.featureFlags['test-environment-3149']) { const localStorageValue = window.localStorage.getItem(ENVIRONMENT_LOCAL_STORAGE_KEY) || Environments.PRODUCTION actions.setFilteredEnvironment(localStorageValue, true) From 9c47d35c8aad6c9026b204a6cd1b9a1f233d8773 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Thu, 13 May 2021 12:54:21 -0400 Subject: [PATCH 28/29] Fixed test --- cypress/integration/commandPalette.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/integration/commandPalette.js b/cypress/integration/commandPalette.js index 633e4ccf4cb2b..b6aedd16254f3 100644 --- a/cypress/integration/commandPalette.js +++ b/cypress/integration/commandPalette.js @@ -5,7 +5,6 @@ describe('Command Palette', () => { }) it('Shows on Ctrl + K press', () => { - cy.get('[data-attr=layout-content]').contains('Insights') cy.get('body').type('{ctrl}k') cy.get('[data-attr=command-palette-input]').should('exist') From f5cb467e5be1849c7295b31d406cc50cab588579 Mon Sep 17 00:00:00 2001 From: Buddy Williams Date: Thu, 13 May 2021 15:13:22 -0400 Subject: [PATCH 29/29] corrected syntax style issues --- posthog/api/capture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posthog/api/capture.py b/posthog/api/capture.py index 1d67eab6028ff..388bda7eb1b38 100644 --- a/posthog/api/capture.py +++ b/posthog/api/capture.py @@ -102,7 +102,7 @@ def _get_token(data, request) -> Optional[str]: def _clean_token(token): is_test_environment = token.startswith("test_") token = token[5:] if is_test_environment else token - return (token, is_test_environment) + return token, is_test_environment def _get_project_id(data, request) -> Optional[int]: