Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(dashboard): user journey smoke tests #7124

Open
wants to merge 41 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e12abe9
chore(dashboard): user journey smoke tests
LetItRock Nov 25, 2024
9f22ad5
chore(dashboard): fix imports in page models
LetItRock Nov 25, 2024
d0a3333
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Nov 25, 2024
ceabff2
chore(dashboard): remove timeout
LetItRock Nov 25, 2024
8ad2e31
chore(api): revert .env.test
LetItRock Nov 25, 2024
461275c
chore(dashboard): fix spell check and adjust pipelines
LetItRock Nov 25, 2024
241dc38
chore(dashboard): e2e pipeline set env variables earlier
LetItRock Nov 25, 2024
1f5180e
chore(dashboard): fixed e2e tests pipeline env config
LetItRock Nov 25, 2024
ead9157
chore(dashboard): fix the e2e tests pipeline
LetItRock Nov 25, 2024
934a828
chore(dashboard): fix the e2e tests pipeline
LetItRock Nov 25, 2024
7bebc12
chore(dashboard): fix the e2e tests pipeline
LetItRock Nov 26, 2024
a7e8329
chore(dashboard): check env keys
LetItRock Nov 26, 2024
c253764
chore(dashboard): fix env keys
LetItRock Nov 26, 2024
fa860f3
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Dec 2, 2024
8c8cb67
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Dec 4, 2024
ba8bf3a
chore(dashboard): updated e2e tests
LetItRock Dec 4, 2024
ebc6c37
chore(dashboard): trying to fix e2e pipeline
LetItRock Dec 4, 2024
2f7b4cf
chore(api): fix used variables
LetItRock Dec 5, 2024
d7f56de
chore(api): fix e2e tests
LetItRock Dec 5, 2024
1aa027a
chore(api): fix e2e tests
LetItRock Dec 5, 2024
addf0fa
chore(api): fix e2e tests
LetItRock Dec 5, 2024
8a70a51
chore(api): fix e2e tests
LetItRock Dec 5, 2024
76c80c0
chore(api): fix e2e tests
LetItRock Dec 5, 2024
a1a5a6b
chore(api): fix e2e tests
LetItRock Dec 5, 2024
9c8f28c
chore(api): fix e2e tests
LetItRock Dec 5, 2024
674861a
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Dec 5, 2024
5727282
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Dec 6, 2024
5d0de32
chore(dashboard): polishing the e2e pipeline
LetItRock Dec 6, 2024
ad68574
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Dec 31, 2024
b670d88
chore(dashboard): add suggestions from the pr #7124
LetItRock Dec 31, 2024
5d69645
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Jan 7, 2025
d2ff14b
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Jan 24, 2025
c69cd24
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Feb 17, 2025
97c5bd7
chore(dashboard): fix lock file
LetItRock Feb 17, 2025
ee801ab
chore(dashboard): refactor e2e tests configuration to use clerk backe…
LetItRock Feb 19, 2025
fb8c6dd
chore(dashboard): update e2e tests pipeline config
LetItRock Feb 20, 2025
c1565e1
Merge branch 'next' into nv-4795-dashboard-user-journey-smoke-tests
LetItRock Feb 20, 2025
5491022
chore(dashboard): update source file for ee repo
LetItRock Feb 20, 2025
f8ceff9
chore(dashboard): run e2e dashboard
LetItRock Feb 20, 2025
8570e9d
chore(dashboard): fix failing e2e
LetItRock Feb 20, 2025
8ec0afa
chore(libs): revert old changes
LetItRock Feb 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/on-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,14 @@ jobs:
# with:
# ee: true

# test_e2e_dashboard:
# name: E2E test Dashboard app
# needs: [get-affected]
# if: ${{ contains(fromJson(needs.get-affected.outputs.test-e2e), '@novu/dashboard') }}
# uses: ./.github/workflows/reusable-dashboard-e2e.yml
# secrets: inherit
# with:
# ee: true
test_e2e_dashboard:
name: E2E test Dashboard app
needs: [get-affected]
if: ${{ contains(fromJson(needs.get-affected.outputs.test-e2e), '@novu/dashboard') }}
uses: ./.github/workflows/reusable-dashboard-e2e.yml
secrets: inherit
with:
ee: true

test_e2e_widget:
name: E2E test Widget
Expand Down
65 changes: 47 additions & 18 deletions .github/workflows/reusable-dashboard-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,30 @@ jobs:
with:
submodules: true

- name: Create .env file for the Dashboard app
working-directory: apps/dashboard
run: |
touch .env
echo VITE_LAUNCH_DARKLY_CLIENT_SIDE_ID=${{ secrets.LAUNCH_DARKLY_CLIENT_SIDE_ID }} >> .env
echo VITE_API_HOSTNAME=http://127.0.0.1:1336 >> .env
echo VITE_WEBSOCKET_HOSTNAME=http://127.0.0.1:1340 >> .env
echo VITE_LEGACY_DASHBOARD_URL=http://127.0.0.1:4200 >> .env
echo VITE_CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_E2E_PUBLISHABLE_KEY }} >> .env
Comment on lines +74 to +79
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.env file for the Dashboard


- name: Create .env file for the Playwright
working-directory: apps/dashboard
run: |
touch .env.playwright
echo NOVU_ENTERPRISE=true >> .env.playwright
echo NEW_RELIC_ENABLED=false >> .env.playwright
echo NEW_RELIC_APP_NAME=Novu >> .env.playwright
echo MONGO_URL=mongodb://127.0.0.1:27017/novu-test >> .env.playwright
echo API_URL=http://127.0.0.1:1336 >> .env.playwright
echo CLERK_ENABLED=true >> .env.playwright
echo CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_E2E_PUBLISHABLE_KEY }} >> .env.playwright
echo CLERK_SECRET_KEY=${{ secrets.CLERK_E2E_SECRET_KEY }} >> .env.playwright
echo NODE_ENV=test >> .env.playwright
Comment on lines +84 to +93
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.env file for the playwright, used to initialize the session, create, and sync users/orgs


- uses: mansagroup/nrwl-nx-action@v3
with:
targets: build
Expand All @@ -77,30 +101,35 @@ jobs:
- uses: ./.github/actions/start-localstack
- uses: ./.github/actions/setup-redis-cluster

- uses: ./.github/actions/run-backend
with:
cypress_github_oauth_client_id: ${{ secrets.CYPRESS_GITHUB_OAUTH_CLIENT_ID }}
cypress_github_oauth_client_secret: ${{ secrets.CYPRESS_GITHUB_OAUTH_CLIENT_SECRET }}
launch_darkly_sdk_key: ${{ secrets.LAUNCH_DARKLY_SDK_KEY }}
ci_ee_test: ${{ steps.determine_run_type.outputs.enterprise_run }}
- name: Start API in TEST
env:
LAUNCH_DARKLY_SDK_KEY: ${{ secrets.LAUNCH_DARKLY_SDK_KEY }}
CI_EE_TEST: true
CLERK_ENABLED: true
CLERK_ISSUER_URL: https://neat-mole-83.clerk.accounts.dev
CLERK_SECRET_KEY: ${{ secrets.CLERK_E2E_SECRET_KEY }}
run: |
cd apps/api && pnpm start:test &

- name: Start Worker
shell: bash
env:
NODE_ENV: 'test'
PORT: '1342'
LAUNCH_DARKLY_SDK_KEY: ${{ secrets.LAUNCH_DARKLY_SDK_KEY }}
CI_EE_TEST: true
run: cd apps/worker && pnpm start:prod &

- name: Wait on API and Worker
shell: bash
run: wait-on --timeout=180000 http://127.0.0.1:1336/v1/health-check http://127.0.0.1:1342/v1/health-check

- name: Start WS
run: |
cd apps/ws && pnpm start:test &

- name: Start Novu Dashboard
working-directory: apps/dashboard
env:
REACT_APP_API_URL: http://127.0.0.1:1336
REACT_APP_WS_URL: http://127.0.0.1:1340
REACT_APP_WEBHOOK_URL: http://127.0.0.1:1341
# Disable LaunchDarkly client-side SDK in the test environment to reduce E2E flakiness
REACT_APP_LAUNCH_DARKLY_CLIENT_SIDE_ID: ''
NOVU_ENTERPRISE: ${{ steps.determine_run_type.outputs.enterprise_run }}
run: pnpm start:static:build &

- name: Wait on Services
run: wait-on --timeout=180000 http://127.0.0.1:1340/v1/health-check http://127.0.0.1:4201/
run: wait-on --timeout=180000 http://127.0.0.1:1340/v1/health-check

- name: Install Playwright
working-directory: apps/dashboard
Expand Down
2 changes: 1 addition & 1 deletion .source
4 changes: 3 additions & 1 deletion apps/dashboard/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ tsconfig.node.tsbuildinfo
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/
.env.test
.env.playwright
9 changes: 9 additions & 0 deletions apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "module",
"scripts": {
"start": "vite",
"start:test": "vite --mode test",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run dashboard and use .env.test file

"start:static:build": "http-server dist -p 4201 --proxy http://127.0.0.1:4201?",
"dev": "pnpm start",
"build": "tsc -b && vite build",
Expand Down Expand Up @@ -105,9 +106,15 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@clerk/backend": "^1.6.2",
"@clerk/testing": "^1.3.27",
Comment on lines +109 to +110
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used to create Clerk user/orgs and to sign-in into the app

"@clerk/types": "^4.30.0",
"@eslint/js": "^9.9.0",
"@faker-js/faker": "^9.5.0",
"@novu/ee-auth": "workspace:*",
"@hookform/devtools": "^4.3.0",
"@novu/dal": "workspace:*",
"@novu/testing": "workspace:*",
Comment on lines +116 to +117
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used to initialize the api session

"@playwright/test": "^1.46.1",
"@sentry/vite-plugin": "^2.22.6",
"@tiptap/core": "^2.10.3",
Expand All @@ -121,6 +128,8 @@
"@types/react-window": "^1.8.8",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20",
"cross-fetch": "^4.0.0",
"dotenv": "^16.4.5",
"eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
Expand Down
31 changes: 26 additions & 5 deletions apps/dashboard/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import { defineConfig, devices } from '@playwright/test';
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
import dotenv from 'dotenv';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const fileName = fileURLToPath(import.meta.url);
const dirName = dirname(fileName);
dotenv.config({ path: path.resolve(dirName, '.env.playwright') });
Comment on lines +12 to +14
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the Dashboard project is configured with "type": "module" this is how we can import the playwright env variables.


const baseURL = `http://localhost:4201`;

/**
* See https://playwright.dev/docs/test-configuration.
Expand All @@ -24,9 +31,15 @@ export default defineConfig({
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? 'blob' : 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
webServer: {
command: 'pnpm start:test',
url: baseURL,
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
},
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:8080',
baseURL: baseURL,

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
Expand All @@ -40,7 +53,15 @@ export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
testMatch: /.*\.e2e\.ts/,
use: {
...devices['Desktop Chrome'],
viewport: { width: 1512, height: 982 },
video: {
mode: 'on-first-retry',
size: { width: 1512, height: 982 },
},
},
},
],
});
1 change: 1 addition & 0 deletions apps/dashboard/src/components/activity/activity-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export function ActivityPanel({ children }: ActivityPanelProps) {
animate={{ opacity: 1 }}
transition={{ duration: 0.5, ease: 'easeOut' }}
className="flex h-full flex-col"
data-testid="activity-panel"
>
{children}
</motion.div>
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/icons/flags/us.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export function USFlag(props: React.SVGProps<SVGSVGElement>) {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<g id="United States" clip-path="url(#clip0_377_4883)">
<g id="United States" clipPath="url(#clip0_377_4883)">
<path
id="Vector"
d="M8 15.999C12.4183 15.999 16 12.4173 16 7.99902C16 3.58075 12.4183 -0.000976562 8 -0.000976562C3.58172 -0.000976562 0 3.58075 0 7.99902C0 12.4173 3.58172 15.999 8 15.999Z"
Expand Down
7 changes: 6 additions & 1 deletion apps/dashboard/src/components/in-app-action-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ export const InAppActionDropdown = ({ onMenuItemClick }: { onMenuItemClick?: ()
<DropdownMenuTrigger className="absolute size-full" tabIndex={-1} />
</div>
<DropdownMenuTrigger asChild>
<CompactButton icon={RiExpandUpDownLine} size="lg" variant="ghost">
<CompactButton
icon={RiExpandUpDownLine}
size="lg"
variant="ghost"
data-testid="in-app-action-dropdown-trigger"
>
<span className="sr-only">Actions</span>
</CompactButton>
</DropdownMenuTrigger>
Expand Down
16 changes: 14 additions & 2 deletions apps/dashboard/src/components/primitives/tag-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,20 @@ const TagInput = forwardRef<HTMLInputElement, TagInputProps>((props, ref) => {
</PopoverAnchor>
<div className="flex flex-wrap gap-2">
{tags.map((tag, index) => (
<Tag key={index} variant="stroke" onDismiss={() => removeTag(tag)}>
<span style={{ wordBreak: 'break-all' }}>{tag}</span>
<Tag
key={index}
variant="stroke"
onDismiss={(e) => {
e.preventDefault();
e.stopPropagation();
Comment on lines +89 to +90
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix the bug - the click on remove button was causing the form submission


removeTag(tag);
}}
dismissTestId={`tags-badge-remove-${tag}`}
>
<span style={{ wordBreak: 'break-all' }} data-testid="tags-badge-value">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some components, I had to add data-tested as there was no accessible way to reference the elements to perform some actions.

{tag}
</span>
</Tag>
))}
</div>
Expand Down
9 changes: 5 additions & 4 deletions apps/dashboard/src/components/primitives/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,19 @@ TagDismissIcon.displayName = TAG_DISMISS_ICON_NAME;
type TagProps = {
children: React.ReactNode;
icon?: React.ReactElement;
onDismiss?: () => void;
onDismiss?: React.MouseEventHandler<HTMLButtonElement>;
asChild?: boolean;
className?: string;
dismissTestId?: string;
} & Pick<VariantProps<typeof tagVariants>, 'variant' | 'disabled'>;

const Tag = React.forwardRef<HTMLDivElement, TagProps>(
({ children, icon, onDismiss, asChild, variant, disabled, className }, ref) => {
({ children, icon, onDismiss, asChild, variant, disabled, className, dismissTestId, ...rest }, ref) => {
return (
<TagRoot ref={ref} asChild={asChild} variant={variant} disabled={disabled} className={className}>
<TagRoot ref={ref} asChild={asChild} variant={variant} disabled={disabled} className={className} {...rest}>
{icon && <TagIcon as={icon.type} {...icon.props} />}
{children}
{onDismiss && <TagDismissButton onClick={onDismiss} disabled={disabled} />}
{onDismiss && <TagDismissButton onClick={onDismiss} disabled={disabled} data-testid={dismissTestId} />}
</TagRoot>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const MenuItem = ({
'text-foreground-300 cursor-not-allowed': disabled,
}
)}
data-testid={`add-step-menu-item-${stepType}`}
>
<Icon
className={`bg-neutral-alpha-50 h-6 w-6 rounded-md p-1 opacity-40`}
Expand Down Expand Up @@ -89,7 +90,7 @@ export const AddStepMenu = ({
}}
>
<PopoverTrigger asChild>
<span data-test-id="add-step-button">
<span data-testid="add-step-menu-button">
<Node
variant="sm"
className={cn('opacity-0 transition duration-300 ease-out hover:opacity-100', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const NodeBody = ({

return (
<HoverCard openDelay={300}>
<HoverCardTrigger>
<HoverCardTrigger asChild>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react warning a nested in a

<div className="bg-neutral-alpha-50 hover-trigger pointer-events-auto relative flex items-center rounded-lg px-1 py-2">
<span className="text-foreground-400 overflow-hidden text-ellipsis text-nowrap text-sm font-medium">
{children}
Expand Down
14 changes: 12 additions & 2 deletions apps/dashboard/src/components/workflow-editor/in-app-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ export const InAppPreviewSubject = (props: InAppPreviewSubjectProps) => {
return <Skeleton className="h-5 w-1/2" />;
}

return <Markdown className={cn('text-foreground-600 truncate text-xs font-medium', className)} {...rest} />;
return (
<Markdown
className={cn('text-foreground-600 truncate text-xs font-medium', className)}
{...rest}
data-testid="in-app-preview-subject"
/>
);
};

type InAppPreviewBodyProps = MarkdownProps & { isPending?: boolean };
Expand All @@ -116,7 +122,11 @@ export const InAppPreviewBody = (props: InAppPreviewBodyProps) => {
}

return (
<Markdown className={cn('text-foreground-400 whitespace-pre-wrap text-xs font-normal', className)} {...rest} />
<Markdown
className={cn('text-foreground-400 whitespace-pre-wrap text-xs font-normal', className)}
{...rest}
data-testid="in-app-preview-body"
/>
);
};

Expand Down
Loading
Loading