Skip to content

Commit

Permalink
Merge branch 'master' into dn/interactions-test
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin committed Nov 23, 2023
2 parents d2a600d + 1961b5b commit 7cd2818
Show file tree
Hide file tree
Showing 1,545 changed files with 16,091 additions and 10,999 deletions.
41 changes: 35 additions & 6 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,25 @@ module.exports = {
},
ecmaVersion: 2018,
sourceType: 'module',
project: 'tsconfig.json'
project: 'tsconfig.json',
},
plugins: ['prettier', 'react', 'cypress', '@typescript-eslint', 'no-only-tests', 'jest', 'compat', 'posthog'],
plugins: [
'prettier',
'react',
'cypress',
'@typescript-eslint',
'no-only-tests',
'jest',
'compat',
'posthog',
'simple-import-sort',
],
rules: {
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-debugger': 'error',
'no-only-tests/no-only-tests': 'error',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'react/prop-types': [0],
'react/react-in-jsx-scope': [0],
'react/no-unescaped-entities': [0],
Expand Down Expand Up @@ -112,6 +124,11 @@ module.exports = {
importNames: ['Tooltip'],
message: 'Please use Tooltip from @posthog/lemon-ui instead.',
},
{
name: 'antd',
importNames: ['Alert'],
message: 'Please use LemonBanner from @posthog/lemon-ui instead.',
},
],
},
],
Expand Down Expand Up @@ -231,6 +248,10 @@ module.exports = {
element: 'a',
message: 'use <Link> instead',
},
{
element: 'Alert',
message: 'use <LemonBanner> instead',
},
],
},
],
Expand All @@ -254,14 +275,22 @@ module.exports = {
rules: {
// The below complains needlessly about expect(api.createInvite).toHaveBeenCalledWith(...)
'@typescript-eslint/unbound-method': 'off',
}
},
},
{
// disable these rules for files generated by kea-typegen
files: ['*Type.ts', '*Type.tsx'],
files: ['*Type.ts', '*Type.tsx'], // Kea typegen output
rules: {
'no-restricted-imports': 'off',
'@typescript-eslint/ban-types': ['off'],
'@typescript-eslint/ban-types': 'off',
'simple-import-sort/imports': 'off',
'simple-import-sort/exports': 'off',
},
},
{
files: ['frontend/src/scenes/notebooks/Nodes/*'], // Notebooks code weirdly relies on its order of sorting
rules: {
'simple-import-sort/imports': 'off',
'simple-import-sort/exports': 'off',
},
},
{
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/container-images-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ jobs:
message: |
{
"image_tag": "${{ steps.build.outputs.digest }}",
"image_tag_unit": "${{ steps.build-unit.outputs.digest }}",
"context": ${{ toJson(github) }}
}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/storybook-chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
container:
image: mcr.microsoft.com/playwright:v1.29.2 # Same as @storybook/test-runner@0.13's dependency
image: mcr.microsoft.com/playwright:v1.32.2 # Same as @storybook/test-runner@0.15.2's dependency
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -144,6 +144,7 @@ jobs:
HOME: /root
# Update snapshots for PRs on the main repo, verify on forks, which don't have access to PostHog Bot
VARIANT: ${{ github.event.pull_request.head.repo.full_name == github.repository && 'update' || 'verify' }}
STORYBOOK_SKIP_TAGS: 'test-skip,test-skip-${{ matrix.browser }}'
run: |
pnpm test:visual-regression:stories:ci:$VARIANT --browsers ${{ matrix.browser }} --shard ${{ matrix.shard }}/$SHARD_COUNT
Expand Down
11 changes: 0 additions & 11 deletions .storybook/decorators/withSnapshotsDisabled.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { getStorybookAppContext } from './app-context'
import { withKea } from './decorators/withKea'
import { withMockDate } from './decorators/withMockDate'
import { defaultMocks } from '~/mocks/handlers'
import { withSnapshotsDisabled } from './decorators/withSnapshotsDisabled'
import { withFeatureFlags } from './decorators/withFeatureFlags'
import { withTheme } from './decorators/withTheme'

Expand Down Expand Up @@ -79,7 +78,6 @@ export const parameters: Parameters = {

// Setup storybook global decorators. See https://storybook.js.org/docs/react/writing-stories/decorators#global-decorators
export const decorators: Meta['decorators'] = [
withSnapshotsDisabled,
// Make sure the msw service worker is started, and reset the handlers to defaults.
withKea,
// Allow us to time travel to ensure our stories don't change over time.
Expand Down
22 changes: 9 additions & 13 deletions .storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toMatchImageSnapshot } from 'jest-image-snapshot'
import { getStoryContext, TestRunnerConfig, TestContext } from '@storybook/test-runner'
import type { Locator, Page, LocatorScreenshotOptions } from 'playwright-core'
import type { Locator, Page, LocatorScreenshotOptions } from '@playwright/test'
import type { Mocks } from '~/mocks/utils'
import { StoryContext } from '@storybook/csf'

Expand All @@ -14,11 +14,6 @@ declare module '@storybook/types' {
options?: any
layout?: 'padded' | 'fullscreen' | 'centered'
testOptions?: {
/**
* Whether the test should be a no-op (doesn't jest.skip as @storybook/test-runner doesn't allow that).
* @default false
*/
skip?: boolean
/**
* Whether we should wait for all loading indicators to disappear before taking a snapshot.
* @default true
Expand Down Expand Up @@ -78,19 +73,20 @@ module.exports = {
jest.retryTimes(RETRY_TIMES, { logErrorsBeforeRetry: true })
jest.setTimeout(JEST_TIMEOUT_MS)
},
async postRender(page, context) {
async postVisit(page, context) {
const browserContext = page.context()
const storyContext = await getStoryContext(page, context)
const { skip = false, snapshotBrowsers = ['chromium'] } = storyContext.parameters?.testOptions ?? {}
const { snapshotBrowsers = ['chromium'] } = storyContext.parameters?.testOptions ?? {}

browserContext.setDefaultTimeout(PLAYWRIGHT_TIMEOUT_MS)
if (!skip) {
const currentBrowser = browserContext.browser()!.browserType().name() as SupportedBrowserName
if (snapshotBrowsers.includes(currentBrowser)) {
await expectStoryToMatchSnapshot(page, context, storyContext, currentBrowser)
}
const currentBrowser = browserContext.browser()!.browserType().name() as SupportedBrowserName
if (snapshotBrowsers.includes(currentBrowser)) {
await expectStoryToMatchSnapshot(page, context, storyContext, currentBrowser)
}
},
tags: {
skip: ['test-skip'], // NOTE: This is overridden by the CI action storybook-chromatic.yml to include browser specific skipping
},
} as TestRunnerConfig

async function expectStoryToMatchSnapshot(
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.playwright
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# We do this to ensure our reference images for visual regression tests are the same during development and in CI.
#

FROM mcr.microsoft.com/playwright:v1.29.2
FROM mcr.microsoft.com/playwright:v1.32.2

WORKDIR /work

Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/featureFlags.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ describe('Feature Flags', () => {
cy.get('[data-attr=save-feature-flag]').first().click()

// after save there should be a delete button
cy.get('[data-attr="more-button"]').click()
cy.get('button[data-attr="delete-feature-flag"]').should('have.text', 'Delete feature flag')

// make sure the data is there as expected after a page reload!
Expand Down Expand Up @@ -83,11 +84,13 @@ describe('Feature Flags', () => {
cy.get('[data-attr=save-feature-flag]').first().click()

// after save there should be a delete button
cy.get('[data-attr="more-button"]').click()
cy.get('button[data-attr="delete-feature-flag"]').should('have.text', 'Delete feature flag')

cy.clickNavMenu('featureflags')
cy.get('[data-attr=feature-flag-table]').should('contain', name)
cy.get(`[data-row-key=${name}]`).contains(name).click()
cy.get('[data-attr="more-button"]').click()
cy.get('[data-attr=delete-feature-flag]').click()
cy.get('.Toastify').contains('Undo').should('be.visible')
})
Expand Down
5 changes: 3 additions & 2 deletions cypress/e2e/insights.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { urls } from 'scenes/urls'
import { randomString } from '../support/random'

import { decideResponse } from '../fixtures/api/decide'
import { savedInsights, createInsight, insight } from '../productAnalytics'
import { createInsight, insight, savedInsights } from '../productAnalytics'
import { randomString } from '../support/random'

// For tests related to trends please check trendsElements.js
// insight tests were split up because Cypress was struggling with this many tests in one file🙈
Expand Down
54 changes: 54 additions & 0 deletions cypress/e2e/surveys.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,58 @@ describe('Surveys', () => {
cy.get('[data-attr=delete-survey]').click()
cy.get('.Toastify__toast-body').contains('Survey deleted').should('be.visible')
})

it('creates a new multiple choice survey with an open-ended choice', () => {
cy.get('h1').should('contain', 'Surveys')
cy.get('[data-attr=new-survey]').click()
cy.get('[data-attr=new-blank-survey]').click()

// add a multiple choice question with an open-ended question
cy.get('[data-attr=survey-name]').focus().type(name).should('have.value', name)
cy.get('[data-attr="survey-question-type-0"]').click()
cy.contains('Multiple choice select').click()
cy.get('button').contains('Add open-ended choice').click()

// check default open-ended choice form input and appearance after
// open-ended choice was added
cy.get('.LemonInput__input[value="Other"]')
cy.get('.choice-option').eq(3).contains('Other:')
cy.get('.choice-option').eq(3).find('input[type="text"]').should('have.value', '')

// typing in open-ended question's appearance automatically checks the
// checkbox
cy.get('.choice-option').eq(3).find('input[type="checkbox"]').should('not.be.checked')
cy.get('.choice-option').eq(3).find('input[type="text"]').type('Outreach')
cy.get('.choice-option').eq(3).find('input[type="checkbox"]').should('be.checked')

// clicking on open-ended question's appearance label unchecks or checks
// the checkbox
cy.get('.choice-option').eq(3).click()
cy.get('.choice-option').eq(3).find('input[type="checkbox"]').should('not.be.checked')
cy.get('.choice-option').eq(3).click()
cy.get('.choice-option').eq(3).find('input[type="checkbox"]').should('be.checked')

// removing text in open-ended question's appearance automatically
// unchecks the checkbox
cy.get('.choice-option').eq(3).find('input[type="text"]').clear()

// open-ended question label doesn't change even if appearance input
// changes
cy.get('.LemonInput__input[value="Other"]')

// change open-ended choice after the label was added
cy.contains('Choices').parent().find('input[type="text"]').eq(3).clear()
cy.contains('Choices').parent().find('input[type="text"]').eq(3).type('First Choice')
cy.get('.choice-option').eq(3).contains('First Choice:')

// attempt to create and save survey
cy.get('[data-attr=save-survey]').first().click()

// after save there should be a launch button
cy.get('button[data-attr="launch-survey"]').should('have.text', 'Launch')

cy.clickNavMenu('surveys')
cy.get('[data-attr=surveys-table]').should('contain', name)
cy.get(`[data-row-key="${name}"]`).contains(name).click()
})
})
2 changes: 1 addition & 1 deletion cypress/e2e/toolbar.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('Toolbar', () => {
.then((href) => {
cy.visit(href)
})
cy.get('#__POSTHOG_TOOLBAR__').shadow().find('.floating-toolbar-button').should('exist')
cy.get('#__POSTHOG_TOOLBAR__').shadow().find('.Toolbar').should('exist')
})
})

Expand Down
1 change: 1 addition & 0 deletions cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ beforeEach(() => {
'surveys-new-creation-flow': true,
'surveys-results-visualizations': true,
'auto-redirect': true,
'surveys-open-choice': true,
notebooks: true,
})
)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/components-command-bar--actions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/components-command-bar--search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/components-compact-list--compact-list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/exporter-exporter--dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/lemon-ui-lemon-input--small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/posthog-3000-keyboard-shortcut--muted.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-dashboards--edit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-dashboards--show.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-insights--trends-number-edit.png
Binary file modified frontend/__snapshots__/scenes-app-insights--trends-number.png
Binary file modified frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png
Binary file modified frontend/__snapshots__/scenes-app-saved-insights--list-view.png
Binary file modified frontend/__snapshots__/scenes-app-surveys--survey-not-found.png
Binary file modified frontend/__snapshots__/scenes-other-settings--settings-project.png
Diff not rendered.
Diff not rendered.
20 changes: 11 additions & 9 deletions frontend/src/exporter/ExportedInsight/ExportedInsight.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { ChartDisplayType, InsightLogicProps, InsightModel } from '~/types'
import './ExportedInsight.scss'

import clsx from 'clsx'
import { BindLogic } from 'kea'
import { insightLogic } from 'scenes/insights/insightLogic'
import { FilterBasedCardContent } from 'lib/components/Cards/InsightCard/InsightCard'
import './ExportedInsight.scss'
import { Logo } from '~/toolbar/assets/Logo'
import { QueriesUnsupportedHere } from 'lib/components/Cards/InsightCard/QueriesUnsupportedHere'
import { TopHeading } from 'lib/components/Cards/InsightCard/TopHeading'
import { InsightLegend } from 'lib/components/InsightLegend/InsightLegend'
import { ExportOptions, ExportType } from '~/exporter/types'
import clsx from 'clsx'
import { SINGLE_SERIES_DISPLAY_TYPES } from 'lib/constants'
import { insightLogic } from 'scenes/insights/insightLogic'
import { isTrendsFilter } from 'scenes/insights/sharedUtils'
import { isDataTableNode } from '~/queries/utils'
import { QueriesUnsupportedHere } from 'lib/components/Cards/InsightCard/QueriesUnsupportedHere'

import { ExportOptions, ExportType } from '~/exporter/types'
import { Query } from '~/queries/Query/Query'
import { TopHeading } from 'lib/components/Cards/InsightCard/TopHeading'
import { isDataTableNode } from '~/queries/utils'
import { Logo } from '~/toolbar/assets/Logo'
import { ChartDisplayType, InsightLogicProps, InsightModel } from '~/types'

export function ExportedInsight({
insight,
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/exporter/Exporter.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useEffect } from 'react'
import { Meta, StoryFn, StoryObj } from '@storybook/react'
import { Exporter } from './Exporter'
import { useEffect } from 'react'

import { dashboard } from '~/exporter/__mocks__/Exporter.mocks'
import { ExportType } from '~/exporter/types'

import { Exporter } from './Exporter'

type Story = StoryObj<typeof Exporter>
const meta: Meta<typeof Exporter> = {
title: 'Exporter/Exporter',
Expand Down
21 changes: 12 additions & 9 deletions frontend/src/exporter/Exporter.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import '~/styles'
import './Exporter.scss'
import { useEffect } from 'react'
import { ExportedData, ExportType } from '~/exporter/types'
import { DashboardPlacement } from '~/types'
import { ExportedInsight } from '~/exporter/ExportedInsight/ExportedInsight'
import { Logo } from '~/toolbar/assets/Logo'
import { Dashboard } from 'scenes/dashboard/Dashboard'
import { useResizeObserver } from 'lib/hooks/useResizeObserver'
import { Link } from 'lib/lemon-ui/Link'

import clsx from 'clsx'
import { useValues } from 'kea'
import { teamLogic } from 'scenes/teamLogic'
import { useResizeObserver } from 'lib/hooks/useResizeObserver'
import { Link } from 'lib/lemon-ui/Link'
import { useEffect } from 'react'
import { Dashboard } from 'scenes/dashboard/Dashboard'
import { SessionRecordingPlayer } from 'scenes/session-recordings/player/SessionRecordingPlayer'
import { SessionRecordingPlayerMode } from 'scenes/session-recordings/player/sessionRecordingPlayerLogic'
import { teamLogic } from 'scenes/teamLogic'

import { ExportedInsight } from '~/exporter/ExportedInsight/ExportedInsight'
import { ExportedData, ExportType } from '~/exporter/types'
import { Logo } from '~/toolbar/assets/Logo'
import { DashboardPlacement } from '~/types'

import { exporterViewLogic } from './exporterViewLogic'

export function Exporter(props: ExportedData): JSX.Element {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/exporter/__mocks__/Exporter.mocks.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { FunnelLayout, ShownAsValue } from 'lib/constants'

import {
ChartDisplayType,
DashboardTile,
Expand All @@ -7,7 +9,6 @@ import {
InsightShortId,
InsightType,
} from '~/types'
import { FunnelLayout, ShownAsValue } from 'lib/constants'

export const dashboard: DashboardType = {
id: 1,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/exporter/exporterViewLogic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { kea, path, props, selectors } from 'kea'
import { ExportedData } from './types'

import type { exporterViewLogicType } from './exporterViewLogicType'
import { ExportedData } from './types'

// This is a simple logic that is mounted by the Exporter view and then can be found by any nested callers
// This simplifies passing props everywhere.
Expand Down
Loading

0 comments on commit 7cd2818

Please sign in to comment.