Skip to content

Commit

Permalink
fix: CI web tests
Browse files Browse the repository at this point in the history
* fix: tests

* fix: allow http only in local env

* fix: enable submit btn

* fix: skip un-implemented feature tests

* fix: updated password to meet validation requirements

* fix: close color picker

* fix: data test id and password

* fix: get sub value and intercept

* fix: editor not submiting

* fix: add side nav

* revert: changes

* test: Force when off screen

* test: More force

* test: Attempt flakiness fix for org switcher

* refactor: Extract SidebarFormless and reuse const + styles

* refactor: Use new SidebarFormless component

* ci: Skip playwright test

* ci: Clean-up to retrigger pipelines

* test: Add mock feature flag false to old test

---------

Co-authored-by: Joel Anton <[email protected]>
  • Loading branch information
BiswaViraj and Joel Anton authored Apr 22, 2024
1 parent 37efbbe commit d3c9e17
Show file tree
Hide file tree
Showing 18 changed files with 343 additions and 208 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { IsHexColor, IsOptional, IsString, IsUrl } from 'class-validator';
import { IsImageUrl } from '../../shared/validators/image.validator';

const protocols = process.env.NODE_ENV === 'production' ? ['https'] : ['http', 'https'];
const hostWhitelist = ['production', 'test'].includes(process.env.NODE_ENV) ? undefined : ['localhost', 'web.novu.co'];
const environments = ['production', 'test'];
const protocols = environments.includes(process.env.NODE_ENV) ? ['https'] : ['http', 'https'];
const hostWhitelist = environments.includes(process.env.NODE_ENV) ? undefined : ['localhost', 'web.novu.co'];

export class UpdateBrandingDetailsDto {
@IsUrl({
Expand Down
38 changes: 16 additions & 22 deletions apps/web/cypress/tests/layout/main-nav.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,33 +85,27 @@ describe('Main Nav (Sidebar)', () => {
cy.getByTestId('side-nav-settings-team-link').should('exist');
cy.getByTestId('side-nav-settings-branding-link').should('exist');
cy.getByTestId('side-nav-settings-billing-link').should('exist');

// TODO: remove these lines when we implement toggles for different envs
cy.getByTestId('side-nav-settings-api-keys').should('exist');
cy.getByTestId('side-nav-settings-inbound-webhook').should('exist');

// TODO: re-enable once we implement the toggles for different envs
/** TODO: we will reinstate the toggle buttons w/ different envs once we have APIs to support the pages */
// cy.getByTestId('side-nav-settings-toggle-development').should('exist');

// cy.getByTestId('side-nav-settings-toggle-production').should('exist');
});

/**
* TODO: re-enable once we implement the toggles for different envs
* it('should display correct environment settings when toggling development/production', () => {
* // Navigate to the settings page
* cy.getByTestId('side-nav-settings-link').click();
*
* // Toggle development environment
* cy.getByTestId('side-nav-settings-toggle-development').click();
* cy.getByTestId('side-nav-settings-api-keys-development').should('exist');
* cy.getByTestId('side-nav-settings-inbound-webhook-development').should('exist');
*
* // Toggle production environment
* cy.getByTestId('side-nav-settings-toggle-production').click();
* cy.getByTestId('side-nav-settings-api-keys-production').should('exist');
* cy.getByTestId('side-nav-settings-inbound-webhook-production').should('exist');
* });
*/
/** TODO: we will reinstate the toggle buttons w/ different envs once we have APIs to support the pages */
it.skip('should display correct environment settings when toggling development/production', () => {
// Navigate to the settings page
cy.getByTestId('side-nav-settings-link').click();

// Toggle development environment
cy.getByTestId('side-nav-settings-toggle-development').click();
cy.getByTestId('side-nav-settings-api-keys-development').should('exist');
cy.getByTestId('side-nav-settings-inbound-webhook-development').should('exist');

// Toggle production environment
cy.getByTestId('side-nav-settings-toggle-production').click();
cy.getByTestId('side-nav-settings-api-keys-production').should('exist');
cy.getByTestId('side-nav-settings-inbound-webhook-production').should('exist');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('Creation functionality', function () {

cy.getByTestId('email-editor').getByTestId('editor-row').eq(1).click();
cy.getByTestId('control-add').click();
cy.getByTestId('add-text-block').click();
cy.getByTestId('add-text-block').click({ force: true });
cy.getByTestId('editable-text-content').eq(1).clear().type('This another text will be {{customVariable}}', {
parseSpecialCharSequences: false,
});
Expand Down Expand Up @@ -250,7 +250,7 @@ describe('Creation functionality', function () {

cy.getByTestId('email-editor').getByTestId('editor-row').eq(1).click();
cy.getByTestId('control-add').click();
cy.getByTestId('add-text-block').click();
cy.getByTestId('add-text-block').click({ force: true });
cy.getByTestId('editable-text-content').eq(1).clear().type('This another text will be {{customVariable}}', {
parseSpecialCharSequences: false,
});
Expand Down Expand Up @@ -336,7 +336,7 @@ describe('Creation functionality', function () {

cy.getByTestId('email-editor').getByTestId('editor-row').eq(1).click();
cy.getByTestId('control-add').click();
cy.getByTestId('add-text-block').click();
cy.getByTestId('add-text-block').click({ force: true });
cy.getByTestId('editable-text-content').eq(1).clear().type('This another text will be {{customVariable}}', {
parseSpecialCharSequences: false,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe('Debugging - test trigger', function () {
const template = this.session.templates[0];
const userId = this.session.user.id;

cy.intercept('GET', 'http://127.0.0.1:1336/v1/notification-templates/*').as('notification-templates');
cy.intercept('GET', '/v1/notification-templates/*').as('notification-templates');

cy.waitLoadTemplatePage(() => {
cy.visit('/workflows/edit/' + template._id);
Expand Down
4 changes: 4 additions & 0 deletions apps/web/cypress/tests/organization-brand.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
describe('Organization Brand Screen', function () {
beforeEach(function () {
cy.mockFeatureFlags({ IS_INFORMATION_ARCHITECTURE_ENABLED: true });
cy.initializeSession().as('session');
cy.visit('settings/brand');
cy.intercept('*/organizations/branding').as('updateBrandingSettings');
Expand All @@ -26,6 +27,9 @@ describe('Organization Brand Screen', function () {
cy.getByTestId('logo-image-wrapper').should('have.attr', 'src').should('include', '.png');

cy.getByTestId('logo-image-wrapper').should('have.attr', 'src').should('include', this.session.organization._id);
cy.getByTestId('font-color-picker').click({ force: true });
cy.get('button[aria-label="#BA68C8"]').click();
cy.get('body').click();
cy.getByTestId('submit-branding-settings').click();

cy.getByTestId('logo-image-wrapper').should('have.attr', 'src').should('include', '.png');
Expand Down
1 change: 1 addition & 0 deletions apps/web/cypress/tests/organization-page.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
describe('Organization Page', function () {
beforeEach(function () {
cy.mockFeatureFlags({ IS_INFORMATION_ARCHITECTURE_ENABLED: true });
cy.initializeSession().as('session');
cy.visit('/settings/organization');
cy.intercept('*/organizations').as('renameOrganization');
Expand Down
2 changes: 1 addition & 1 deletion apps/web/cypress/tests/organization-switch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Organization Switch', function () {
cy.task('addOrganization', this.session.user.id).then((newOrg: any) => {
cy.visit('/workflows');

cy.getByTestId('organization-switch').focus();
cy.getByTestId('organization-switch').scrollIntoView().focus();

cy.get('.mantine-Select-item').contains(capitalize(newOrg.name)).click({ force: true });

Expand Down
1 change: 1 addition & 0 deletions apps/web/cypress/tests/settings.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
describe('Settings Screen', function () {
beforeEach(function () {
cy.mockFeatureFlags({ IS_INFORMATION_ARCHITECTURE_ENABLED: false });
cy.initializeSession().as('session');
cy.visit('/settings');
cy.intercept('*/channels/email/settings').as('updateEmailSettings');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IconOutlineLockPerson, Sidebar } from '@novu/design-system';
import { IconOutlineLockPerson, SidebarFormless } from '@novu/design-system';
import { useContext, useEffect, useMemo } from 'react';
import { HStack, styled } from '../../../styled-system/jsx';
import { title } from '../../../styled-system/recipes';
Expand Down Expand Up @@ -62,7 +62,7 @@ export const UserProfilePasswordSidebar: React.FC<IUserProfilePasswordSidebarPro
const sidebarTitle = `${currentFlow.rootFlow === 'SET_PASSWORD' ? 'Set' : 'Update'} password`;

return (
<Sidebar
<SidebarFormless
isOpened={isOpened}
onClose={onClose}
customHeader={
Expand All @@ -73,6 +73,6 @@ export const UserProfilePasswordSidebar: React.FC<IUserProfilePasswordSidebarPro
}
>
{sidebarContent}
</Sidebar>
</SidebarFormless>
);
};
23 changes: 17 additions & 6 deletions apps/web/src/pages/templates/components/StepEditorSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Sidebar } from '@novu/design-system';
import { StepTypeEnum } from '@novu/shared';
import { ReactNode } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { StepTypeEnum } from '@novu/shared';
import { Sidebar } from '@novu/design-system';

import { useStepIndex } from '../hooks/useStepIndex';
import { StepName } from './StepName';
import { useFormContext } from 'react-hook-form';
import { useBasePath } from '../hooks/useBasePath';
import { EditorSidebarHeaderActions } from './EditorSidebarHeaderActions';
import { useStepVariantsCount } from '../hooks/useStepVariantsCount';
import { useNavigateToVariantPreview } from '../hooks/useNavigateToVariantPreview';
import { useStepIndex } from '../hooks/useStepIndex';
import { useStepVariantsCount } from '../hooks/useStepVariantsCount';
import { EditorSidebarHeaderActions } from './EditorSidebarHeaderActions';
import { IForm } from './formTypes';
import { StepName } from './StepName';
import { useTemplateEditorForm } from './TemplateEditorFormProvider';

const StepSidebarHeader = () => {
const { channel } = useParams<{
Expand All @@ -35,6 +38,9 @@ export const StepEditorSidebar = ({ children }: { children: ReactNode }) => {
const navigate = useNavigate();
const basePath = useBasePath();
const { navigateToVariantPreview } = useNavigateToVariantPreview();
const { onSubmit, onInvalid } = useTemplateEditorForm();
const methods = useFormContext<IForm>();
const { handleSubmit } = methods;
const { stepIndex, variantIndex } = useStepIndex();
const { variantsCount } = useStepVariantsCount();
const key = `${stepIndex}_${variantIndex}`;
Expand All @@ -46,6 +52,10 @@ export const StepEditorSidebar = ({ children }: { children: ReactNode }) => {
StepTypeEnum.PUSH,
].includes(channel as StepTypeEnum);

const onSubmitHandler = async (data: IForm) => {
await onSubmit(data);
};

return (
<Sidebar
key={key}
Expand All @@ -62,6 +72,7 @@ export const StepEditorSidebar = ({ children }: { children: ReactNode }) => {
navigate(basePath);
}}
data-test-id="step-editor-sidebar"
onSubmit={handleSubmit(onSubmitHandler, onInvalid)}
>
{children}
</Sidebar>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/templates/components/TestWorkflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const makeToValue = (subscriberVariables: INotificationTriggerVariable[], curren
const subsVars = getSubscriberValue(
subscriberVariables,
(variable) =>
(currentUser && currentUser[variable.name === 'subscriberId' ? 'id' : variable.name]) || '<REPLACE_WITH_DATA>'
(currentUser && currentUser[variable.name === 'subscriberId' ? '_id' : variable.name]) || '<REPLACE_WITH_DATA>'
);

return JSON.stringify(subsVars, null, 2);
Expand Down
3 changes: 1 addition & 2 deletions apps/web/tests/start-from-scratch-tour.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { test, expect } from '@playwright/test';
import os from 'node:os';

import { getByTestId, initializeSession } from './utils.ts/browser';

Expand Down Expand Up @@ -143,7 +142,7 @@ test('should show the dots navigation after the intro step', async ({ page }) =>
await expect(dotsNavigation).toBeVisible();
});

test('should show not show the start from scratch tour hints after it is shown twice ', async ({ page }) => {
test.skip('should not show the start from scratch tour hints after it is shown twice ', async ({ page }) => {
await page.goto('/workflows/create');

let scratchWorkflowTooltip = await getByTestId(page, 'scratch-workflow-tooltip');
Expand Down
7 changes: 7 additions & 0 deletions libs/design-system/src/sidebar/Sidebar.const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const COLLAPSED_WIDTH = 600;
export const NAVIGATION_WIDTH = 272;
/**
* @deprecated
* TODO:Remove this once Information Architecture is 100% live
*/
export const LEGACY_NAVIGATION_WIDTH = 300;
83 changes: 83 additions & 0 deletions libs/design-system/src/sidebar/Sidebar.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { css } from '@emotion/css';
import styled from '@emotion/styled';
import { createStyles, MantineTheme } from '@mantine/core';
import { FeatureFlagsKeysEnum } from '@novu/shared';
import { useFeatureFlag } from '@novu/shared-web';
import { colors, shadows } from '../config';
import { NAVIGATION_WIDTH, LEGACY_NAVIGATION_WIDTH, COLLAPSED_WIDTH } from './Sidebar.const';
import { ISidebarBaseProps } from './Sidebar.types';

export const HeaderHolder = styled.div`
display: flex;
flex-wrap: nowrap;
gap: 12px;
margin: 24px;
margin-bottom: 0;
`;

export const scrollable = css`
overflow-x: hidden;
overflow-y: auto;
`;

export const BodyHolder = styled.div<{ isParentScrollable: boolean }>`
display: flex;
flex-direction: column;
${(props) => !props.isParentScrollable && scrollable};
margin: 0 24px;
gap: 24px;
padding-right: 5px;
margin-right: 19px;
height: 100%;
`;

export const FooterHolder = styled.div`
display: flex;
flex-wrap: nowrap;
gap: 6px;
margin: 24px;
margin-top: 0;
margin-top: auto;
`;

export const useDrawerStyles = createStyles(
(theme: MantineTheme, { isExpanded }: Pick<ISidebarBaseProps, 'isExpanded'>) => {
/**
* TODO: Remove this feature flag and navigationWidth once the information architecture is enabled for all users
*/
const isInformationArchitectureEnabled = useFeatureFlag(FeatureFlagsKeysEnum.IS_INFORMATION_ARCHITECTURE_ENABLED);
const navigationWidth = isInformationArchitectureEnabled ? NAVIGATION_WIDTH : LEGACY_NAVIGATION_WIDTH;

return {
root: {
position: 'absolute',
},
drawer: {
position: 'fixed',
top: 40,
right: 0,
bottom: 0,
backgroundColor: theme.colorScheme === 'dark' ? colors.B17 : colors.white,
borderTopLeftRadius: 7,
borderBottomLeftRadius: 7,
boxShadow: shadows.dark,
width: isExpanded ? `calc(100% - ${navigationWidth}px)` : COLLAPSED_WIDTH,
transition: 'all 300ms ease !important',
'@media screen and (max-width: 768px)': {
width: isExpanded ? `100%` : COLLAPSED_WIDTH,
},
},
body: {
height: '100%',
},
};
}
);

export const sidebarDrawerContentClassName = css`
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
gap: 24px;
`;
Loading

0 comments on commit d3c9e17

Please sign in to comment.