diff --git a/cypress/e2e/early-access-management.cy.ts b/cypress/e2e/early-access-management.cy.ts new file mode 100644 index 0000000000000..9a594d8d1c34c --- /dev/null +++ b/cypress/e2e/early-access-management.cy.ts @@ -0,0 +1,55 @@ +describe('Early Access Management', () => { + beforeEach(() => { + cy.visit('/early_access_features') + }) + + it('Early access feature new and list', () => { + // load an empty early access feature page + cy.get('h1').should('contain', 'Early Access Management') + cy.title().should('equal', 'Early Access Management • PostHog') + cy.get('h2').should('contain', 'Create your first feature') + cy.get('[data-attr="product-introduction-docs-link"]').should( + 'contain', + 'Learn more about Early access features' + ) + + // go to create a new feature + cy.get('[data-attr="create-feature"]').click() + + // New Feature Release page + cy.get('h1').should('contain', 'New Feature Release') + + // cancel new feature + cy.get('[data-attr="cancel-feature"]').click() + cy.get('h1').should('contain', 'Early Access Management') + + // set feature name & description + cy.get('[data-attr="create-feature"]').click() + cy.get('[data-attr="feature-name"]').type('Test Feature') + cy.get('[data-attr="save-feature').should('contain.text', 'Save as draft') + + // save + cy.get('[data-attr="save-feature"]').click() + cy.get('[data-attr=success-toast]').contains('Early Access Feature saved').should('exist') + + // back to features + cy.visit('/early_access_features') + cy.get('tbody').contains('Test Feature') + cy.get('h2').should('not.have.text', 'Create your first feature') + + // edit feature + cy.get('a.Link').contains('.row-name', 'Test Feature').click() + cy.get('[data-attr="edit-feature"]').click() + cy.get('h1').should('contain', 'Test Feature') + cy.get('[data-attr="save-feature"]').should('contain.text', 'Save') + + // delete feature + cy.get('[data-attr="save-feature"]').click() + cy.get('[data-attr="delete-feature"]').click() + cy.get('h3').should('contain', 'Permanently delete feature?') + cy.get('[data-attr="confirm-delete-feature"]').click() + cy.get('[data-attr=info-toast]') + .contains('Early access feature deleted. Remember to delete corresponding feature flag if necessary') + .should('exist') + }) +}) diff --git a/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx b/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx index 2677d3fb1ccec..a894b964432cf 100644 --- a/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx +++ b/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx @@ -48,8 +48,13 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element { isEditingFeature, earlyAccessFeatureMissing, } = useValues(earlyAccessFeatureLogic) - const { submitEarlyAccessFeatureRequest, cancel, editFeature, updateStage, deleteEarlyAccessFeature } = - useActions(earlyAccessFeatureLogic) + const { + submitEarlyAccessFeatureRequest, + loadEarlyAccessFeature, + editFeature, + updateStage, + deleteEarlyAccessFeature, + } = useActions(earlyAccessFeatureLogic) const isNewEarlyAccessFeature = id === 'new' || id === undefined @@ -72,7 +77,15 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element { <> cancel()} + data-attr="cancel-feature" + onClick={() => { + if (isEditingFeature) { + editFeature(false) + loadEarlyAccessFeature() + } else { + router.actions.push(urls.earlyAccessFeatures()) + } + }} disabledReason={isEarlyAccessFeatureSubmitting ? 'Saving…' : undefined} > Cancel @@ -80,6 +93,7 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element { { submitEarlyAccessFeatureRequest(earlyAccessFeature) }} @@ -103,6 +117,7 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element { children: 'Delete', type: 'primary', status: 'danger', + 'data-attr': 'confirm-delete-feature', onClick: () => { // conditional above ensures earlyAccessFeature is not NewEarlyAccessFeature deleteEarlyAccessFeature( @@ -148,7 +163,12 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element { )} {earlyAccessFeature.stage != EarlyAccessFeatureStage.GeneralAvailability && ( - editFeature(true)} loading={false}> + editFeature(true)} + loading={false} + data-attr="edit-feature" + > Edit )} diff --git a/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx b/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx index c6dc0c2c83cf0..594a986400042 100644 --- a/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx +++ b/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx @@ -60,7 +60,7 @@ export function EarlyAccessFeatures(): JSX.Element { } buttons={ - New public beta + Create feature } delimited diff --git a/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts b/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts index 96ce8ab5eac2d..df5aabcc583b9 100644 --- a/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts +++ b/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts @@ -40,7 +40,6 @@ export const earlyAccessFeatureLogic = kea([ actions({ setEarlyAccessFeatureMissing: true, toggleImplementOptInInstructionsModal: true, - cancel: true, editFeature: (editing: boolean) => ({ editing }), updateStage: (stage: EarlyAccessFeatureStage) => ({ stage }), deleteEarlyAccessFeature: (earlyAccessFeatureId: EarlyAccessFeatureType['id']) => ({ earlyAccessFeatureId }), @@ -130,12 +129,6 @@ export const earlyAccessFeatureLogic = kea([ ], }), listeners(({ actions, values, props }) => ({ - cancel: () => { - if ('id' in values.earlyAccessFeature) { - actions.loadEarlyAccessFeature() - } - actions.editFeature(false) - }, updateStage: async ({ stage }) => { 'id' in values.earlyAccessFeature && (await api.earlyAccessFeatures.update(props.id, {