Skip to content

Commit

Permalink
chore(web): improvements for the onboarding cypress e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
LetItRock committed Feb 27, 2024
1 parent 3eb9491 commit d6d8011
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 98 deletions.
92 changes: 91 additions & 1 deletion apps/web/cypress/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ import {
EnvironmentService,
} from '@novu/testing';
import { JobsService } from '@novu/testing';
import { ChannelTypeEnum, getPopularTemplateIds, ProvidersIdEnum } from '@novu/shared';
import {
ChannelTypeEnum,
getPopularTemplateIds,
getGetStartedTemplateIds,
ProvidersIdEnum,
TriggerTypeEnum,
StepTypeEnum,
} from '@novu/shared';

const jobsService = new JobsService();

Expand Down Expand Up @@ -198,6 +205,11 @@ module.exports = (on, config) => {
_environmentId: productionEnvironmentId,
_organizationId: organizationId,
});
const productionGetStartedlGroup = await notificationGroupRepository.findOne({

Check warning on line 208 in apps/web/cypress/plugins/index.ts

View workflow job for this annotation

GitHub Actions / Spell check

Unknown word (Startedl)
name: 'Get started',
_environmentId: productionEnvironmentId,
_organizationId: organizationId,
});

if (!productionGeneralGroup) {
await notificationGroupRepository.create({
Expand All @@ -206,6 +218,13 @@ module.exports = (on, config) => {
_organizationId: organizationId,
});
}
if (!productionGetStartedlGroup) {
await notificationGroupRepository.create({
name: 'Get started',
_environmentId: productionEnvironmentId,
_organizationId: organizationId,
});
}

const productionNotificationTemplateService = new NotificationTemplateService(
user._id,
Expand All @@ -214,6 +233,7 @@ module.exports = (on, config) => {
);

const popularTemplateIds = getPopularTemplateIds({ production: false });
const getStartedTemplateIds = getGetStartedTemplateIds({ production: false });

const blueprintTemplates = await productionNotificationTemplateService.getBlueprintTemplates(
organizationId,
Expand All @@ -236,6 +256,76 @@ module.exports = (on, config) => {
name: ':fa-solid fa-lock: Password reset',
isBlueprint: true,
}),
productionNotificationTemplateService.createTemplate({
_id: getStartedTemplateIds[0],
noFeedId: true,
noLayoutId: true,
name: ':fa-solid fa-clock: Delay',
isBlueprint: true,
steps: [
{
type: StepTypeEnum.DELAY,
name: 'Delay',
content: '',
},
],
triggers: [
{
identifier: 'get-started-delay',
type: TriggerTypeEnum.EVENT,
variables: [],
},
],
}),
productionNotificationTemplateService.createTemplate({
_id: getStartedTemplateIds[1],
noFeedId: true,
noLayoutId: true,
name: ':fa-solid fa-layer-group: Digest',
isBlueprint: true,
steps: [
{
type: StepTypeEnum.DIGEST,
name: 'Digest',
content: '',
},
],
triggers: [
{
identifier: 'get-started-digest',
type: TriggerTypeEnum.EVENT,
variables: [],
},
],
}),
productionNotificationTemplateService.createTemplate({
_id: getStartedTemplateIds[2],
noFeedId: true,
noLayoutId: true,
name: ':fa-solid fa-bell: In-App',
isBlueprint: true,
triggers: [
{
identifier: 'get-started-in-app',
type: TriggerTypeEnum.EVENT,
variables: [],
},
],
}),
productionNotificationTemplateService.createTemplate({
_id: getStartedTemplateIds[3],
noFeedId: true,
noLayoutId: true,
name: ':fa-solid fa-earth-americas: Multi-channel',
isBlueprint: true,
triggers: [
{
identifier: 'get-started-multi-channel',
type: TriggerTypeEnum.EVENT,
variables: [],
},
],
}),
]);
}

Expand Down
152 changes: 90 additions & 62 deletions apps/web/cypress/tests/get-started-page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ interface ITabLinkInfo {
label: string;
type: 'button' | 'a';
urlRegex: RegExp;
windowOpenCallIndex?: number;
}

interface ITabTest {
Expand All @@ -15,8 +16,11 @@ const BASE_ROUTE = '/get-started';

const visitTabAndVerifyContent = ({ tabName, tabTitle, numTimelineSteps, linkSteps }: ITabTest) => {
cy.visit(BASE_ROUTE);
cy.window().then((win) => {
cy.stub(win, 'open').as('windowOpen');
});

cy.contains(tabName).click();
cy.contains(tabName).as('tab').click();

// Check that the clicked tab is now selected
cy.get('button[role="tab"][aria-selected="true"]').contains(tabName).should('exist');
Expand All @@ -38,23 +42,38 @@ const visitTabAndVerifyContent = ({ tabName, tabTitle, numTimelineSteps, linkSte
});

// validate various links, open them, and go back to the tab
linkSteps.forEach(({ urlRegex, label, type }) => {
cy.contains(type, label).should('be.visible').click();

cy.url().should('match', urlRegex);

cy.go('back');
linkSteps.forEach(({ urlRegex, label, type, windowOpenCallIndex }) => {
cy.contains(type, label).should('be.visible');
if (type === 'a') {
cy.contains(type, label).should('have.attr', 'target', '_blank');
cy.contains(type, label).should('have.attr', 'rel', 'noopener noreferrer');
cy.contains(type, label).should('have.attr', 'href').should('match', urlRegex);
} else {
const index = windowOpenCallIndex ?? 0;
cy.contains(type, label).click();
cy.get('@windowOpen')
.its('callCount')
.should('equal', index + 1);

// FIXME: required until feature flag check is removed since we always end up back on `in-app` tab
cy.contains(tabName).click();
cy.get('@windowOpen')
.its('args')
.then((args) => {
const newTabUrl = args[index][0];
const target = args[index][1];
const rel = args[index][2];
expect(newTabUrl).to.match(urlRegex);
expect(target).to.equal('_blank');
expect(rel).to.equal('noreferrer noopener');
});
}
});
};

describe('GetStartedPage', () => {
beforeEach(function () {
cy.mockFeatureFlags({ IS_IMPROVED_ONBOARDING_ENABLED: true });

cy.initializeSession().as('session');
cy.makeBlueprints();
});

it('should have all tabs and default to in-app', () => {
Expand All @@ -71,8 +90,7 @@ describe('GetStartedPage', () => {
cy.get('button[role="tab"][aria-selected="true"]').contains('In-app').should('exist');
});

// FIXME: this will fail until we remove the conditional load based on feature-flag
it.skip('should load the page with a specific tab selected when the appropriate URL search param is passed', () => {
it('should load the page with a specific tab selected when the appropriate URL search param is passed', () => {
cy.visit(`${BASE_ROUTE}?tab=multi-channel`);

// Check that In-app is defaulted and selected
Expand All @@ -90,16 +108,18 @@ describe('GetStartedPage', () => {
type: 'a',
urlRegex: new RegExp('/integrations/[A-Z0-9]+', 'i'),
},
/* // {
// label: 'Customize',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Test the trigger',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// }, */
{
label: 'Customize',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}/,
windowOpenCallIndex: 0,
},
{
label: 'Test the trigger',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/test-workflow/,
windowOpenCallIndex: 1,
},
{
label: 'activity feed',
type: 'a',
Expand All @@ -120,16 +140,18 @@ describe('GetStartedPage', () => {
type: 'a',
urlRegex: new RegExp('/integrations/create'),
},
/* // {
// label: 'Customize',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Test the trigger',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// }, */
{
label: 'Customize',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}/,
windowOpenCallIndex: 0,
},
{
label: 'Test the trigger',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/test-workflow/,
windowOpenCallIndex: 1,
},
{
label: 'activity feed',
type: 'a',
Expand All @@ -150,21 +172,24 @@ describe('GetStartedPage', () => {
type: 'a',
urlRegex: new RegExp('/integrations/create'),
},
/* // {
// label: 'Customize',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Customize digest node',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Test the trigger',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// }, */
{
label: 'Customize',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}/,
windowOpenCallIndex: 0,
},
{
label: 'Customize digest node',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/digest\/\w{1,}/,
windowOpenCallIndex: 1,
},
{
label: 'Test the trigger',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/test-workflow/,
windowOpenCallIndex: 2,
},
{
label: 'activity feed',
type: 'a',
Expand All @@ -185,21 +210,24 @@ describe('GetStartedPage', () => {
type: 'a',
urlRegex: new RegExp('/integrations/create'),
},
/* // {
// label: 'Customize',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Customize delay',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// },
// {
// label: 'Test the trigger',
// type: 'button',
// urlRegex: new RegExp('/workflows'),
// }, */
{
label: 'Customize',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}/,
windowOpenCallIndex: 0,
},
{
label: 'Customize delay',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/delay\/\w{1,}/,
windowOpenCallIndex: 1,
},
{
label: 'Test the trigger',
type: 'button',
urlRegex: /\/workflows\/edit\/\w{1,}\/test-workflow/,
windowOpenCallIndex: 2,
},
{
label: 'activity feed',
type: 'a',
Expand Down
1 change: 0 additions & 1 deletion apps/web/cypress/tests/templates-store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ describe('Templates Store', function () {
cy.getByTestId('all-workflow-tile').should('exist').should('not.be.disabled').click();
cy.getByTestId('templates-store-modal').should('be.visible');
cy.getByTestId('templates-store-modal-use-template').should('be.enabled').click();
cy.getByTestId('templates-store-modal-use-template').should('be.disabled');

cy.wait('@createTemplate');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { errorMessage } from '@novu/design-system';
import { TemplateCreationSourceEnum } from '../../templates/shared';
import { useSegment } from '../../../components/providers/SegmentProvider';
import { OnboardingWorkflowRouteEnum } from '../consts/types';
import { StyledLink } from '../consts/shared';
import { LinkButton } from '../consts/shared';
import { useCreateWorkflowFromBlueprint } from '../../../hooks';
import { openInNewTab } from '../../../utils';
import { buildWorkflowEditorUrl } from '../utils/workflowEditorUrl';
Expand Down Expand Up @@ -35,5 +35,5 @@ export function OpenWorkflowButton({
createWorkflowFromBlueprint({ blueprintIdentifier });
};

return <StyledLink onClick={handleOpenWorkflowClick}>{children}</StyledLink>;
return <LinkButton onClick={handleOpenWorkflowClick}>{children}</LinkButton>;
}
Loading

0 comments on commit d6d8011

Please sign in to comment.