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

test: Add Sveltekit E2E tests #695

Merged
merged 6 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,13 @@ jobs:
run: yarn test

job_e2e_test:
name: End-to-End Tests
name: ${{ matrix.wizard }} E2E Tests
needs: job_build
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
wizard: [NextJS, Remix, Sveltekit]
env:
SENTRY_TEST_AUTH_TOKEN: ${{ secrets.E2E_TEST_SENTRY_AUTH_TOKEN }}
SENTRY_TEST_ORG: 'sentry-javascript-sdks'
Expand All @@ -86,4 +89,4 @@ jobs:
- name: Install dependencies with yarn
run: yarn install --frozen-lockfile
- name: Run End-to-End Tests
run: yarn test:e2e
run: yarn test:e2e:run ${{ matrix.wizard }}
21 changes: 21 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
node_modules

# Output
.output
.vercel
/.svelte-kit
/build

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions e2e-tests/test-applications/sveltekit-test-app/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
21 changes: 21 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "sveltekit-test-app",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^5.0.3"
}
}
13 changes: 13 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}

export {};
11 changes: 11 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
18 changes: 18 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),

kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
}
};

export default config;
19 changes: 19 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}
6 changes: 6 additions & 0 deletions e2e-tests/test-applications/sveltekit-test-app/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [sveltekit()]
});
6 changes: 4 additions & 2 deletions e2e-tests/tests/nextjs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ describe('NextJS', () => {
reactComponentAnnotationsPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER],
'Do you want to enable Tracing',
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
'to track the performance of your application?',
));

const replayOptionPrompted =
tracingOptionPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER],
'Do you want to enable Sentry Session Replay',
// "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
'to get a video-like reproduction of errors during a user session?',
));

const examplePagePrompted =
Expand Down
16 changes: 8 additions & 8 deletions e2e-tests/tests/remix.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@
import { Integration } from '../../lib/Constants';
import {
checkEnvBuildPlugin,
cleanupGit,
KEYS,
revertLocalChanges,
} from '../utils';
import { startWizardInstance } from '../utils';
import {
checkFileContents,
checkFileExists,
checkIfBuilds,
checkIfRunsOnDevMode,
checkIfRunsOnProdMode,
checkPackageJson,
cleanupGit,
KEYS,
revertLocalChanges,
startWizardInstance,
TEST_ARGS,
} from '../utils';
import * as path from 'path';
Expand All @@ -36,7 +34,8 @@ describe('Remix', () => {
(await wizardInstance.sendStdinAndWaitForOutput(
// Selecting `yarn` as the package manager
[KEYS.DOWN, KEYS.ENTER],
'Do you want to enable Tracing',
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
'to track the performance of your application?',
{
timeout: 240_000,
},
Expand All @@ -46,7 +45,8 @@ describe('Remix', () => {
tracingOptionPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER],
'Do you want to enable Sentry Session Replay',
// "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
'to get a video-like reproduction of errors during a user session?',
));

replayOptionPrompted &&
Expand Down
154 changes: 154 additions & 0 deletions e2e-tests/tests/sveltekit.test.ts
Copy link
Member

Choose a reason for hiding this comment

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

Can we add or adjust a test that checks for replayIntegration being added and tracesSampleRate: 1.0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, added 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/* eslint-disable jest/expect-expect */
import { Integration } from '../../lib/Constants';
import {
checkEnvBuildPlugin,
checkFileContents,
checkFileExists,
checkIfBuilds,
checkIfRunsOnDevMode,
checkIfRunsOnProdMode,
checkPackageJson,
cleanupGit,
KEYS,
revertLocalChanges,
startWizardInstance,
TEST_ARGS,
} from '../utils';
import * as path from 'path';

describe('Sveltekit', () => {
const integration = Integration.sveltekit;
const projectDir = path.resolve(
__dirname,
'../test-applications/sveltekit-test-app',
);

beforeAll(async () => {
const wizardInstance = startWizardInstance(integration, projectDir);

const packageManagerPrompted = await wizardInstance.waitForOutput(
'Please select your package manager.',
{
optional: true,
}
);

const tracingOptionPrompted =
packageManagerPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
// Selecting `yarn` as the package manager
[KEYS.DOWN, KEYS.ENTER],
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
'to track the performance of your application?',
{
timeout: 240_000,
}
));

const replayOptionPrompted =
tracingOptionPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER],
// "Do you want to enable Sentry Session Replay", sometimes doesn't work as `Sentry Session Replay` can be printed in bold.
'to get a video-like reproduction of errors during a user session?',
));

replayOptionPrompted &&
(await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER],
'Do you want to create an example page',
{
optional: true,
},
));

await wizardInstance.sendStdinAndWaitForOutput(
[KEYS.ENTER, KEYS.ENTER],
'Successfully installed the Sentry SvelteKit SDK!',
);

wizardInstance.kill();
});

afterAll(() => {
revertLocalChanges(projectDir);
cleanupGit(projectDir);
});

test('should have the correct package.json', () => {
checkPackageJson(projectDir, integration);
});

test('should have the correct .env.sentry-build-plugin', () => {
checkEnvBuildPlugin(projectDir);
});

test('example page exists', () => {
checkFileExists(path.resolve(projectDir, 'src/routes/sentry-example/+page.svelte'));
checkFileExists(path.resolve(projectDir, 'src/routes/sentry-example/+server.js'));
});

test('vite.config contains sentry plugin', () => {
checkFileContents(path.resolve(projectDir, 'vite.config.ts'), `plugins: [sentrySvelteKit({
sourceMapsUploadOptions: {
`);
});

test('hook files created', () => {
checkFileExists(path.resolve(projectDir, 'src/hooks.server.ts'));
checkFileExists(path.resolve(projectDir, 'src/hooks.client.ts'));
});

test('hooks.client.ts contains sentry import', () => {
checkFileContents(
path.resolve(projectDir, 'src/hooks.client.ts'),
[`import * as Sentry from '@sentry/sveltekit';`,
`Sentry.init({
dsn: '${TEST_ARGS.PROJECT_DSN}',

tracesSampleRate: 1.0,

// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
replaysSessionSampleRate: 0.1,

// If the entire session is not sampled, use the below sample rate to sample
// sessions when an error occurs.
replaysOnErrorSampleRate: 1.0,

// If you don't want to use Session Replay, just remove the line below:
integrations: [replayIntegration()],
});`]);
});


test('hooks.server.ts contains sentry import', () => {
checkFileContents(
path.resolve(projectDir, 'src/hooks.server.ts'),
[
`import * as Sentry from '@sentry/sveltekit';`,
`Sentry.init({
dsn: '${TEST_ARGS.PROJECT_DSN}',

tracesSampleRate: 1.0,

// uncomment the line below to enable Spotlight (https://spotlightjs.com)
// spotlight: import.meta.env.DEV,
});`])
});


test('runs on dev mode correctly', async () => {
await checkIfRunsOnDevMode(projectDir, 'ready in');
});

test('should build successfully', async () => {
await checkIfBuilds(projectDir, 'Successfully uploaded source maps to Sentry');
});

test('runs on prod mode correctly', async () => {
// We can't use the full prompt `Network: use--host to expose` as `--host` can be printed in bold.
await checkIfRunsOnProdMode(projectDir, 'to expose', "preview");
});
});

3 changes: 2 additions & 1 deletion e2e-tests/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
execSync('git commit -m init', { cwd: projectDir });
} catch (e) {
log.error('Error initializing git');
log.error(e);

Check warning on line 150 in e2e-tests/utils/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Unsafe argument of type `any` assigned to a parameter of type `string`
}
}

Expand All @@ -161,10 +161,10 @@
export function cleanupGit(projectDir: string): void {
try {
// Remove the .git directory
execSync(`rm -rf ${projectDir}/.git`);

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.
This shell command depends on an uncontrolled
absolute path
.
This shell command depends on an uncontrolled
absolute path
.
This shell command depends on an uncontrolled absolute path.
This shell command depends on an uncontrolled absolute path.
} catch (e) {
log.error('Error cleaning up git');
log.error(e);

Check warning on line 167 in e2e-tests/utils/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Unsafe argument of type `any` assigned to a parameter of type `string`
}
}

Expand All @@ -184,7 +184,7 @@
execSync('git clean -fd .', { cwd: projectDir });
} catch (e) {
log.error('Error reverting local changes');
log.error(e);

Check warning on line 187 in e2e-tests/utils/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Unsafe argument of type `any` assigned to a parameter of type `string`
}
}

Expand Down Expand Up @@ -330,8 +330,9 @@
export async function checkIfRunsOnProdMode(
projectDir: string,
expectedOutput: string,
startCommand = 'start',
) {
const testEnv = new WizardTestEnv('npm', ['run', 'start'], {
const testEnv = new WizardTestEnv('npm', ['run', startCommand], {
cwd: projectDir,
});

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"fix:eslint": "eslint . --format stylish --fix",
"test": "yarn build && jest",
"test:e2e": "yarn build && jest -c=\"./e2e-tests/jest.config.ts\" ./e2e-tests/ --runInBand",
"test:e2e:run": "yarn build && jest -c=\"./e2e-tests/jest.config.ts\" ./e2e-tests/ -t",
"try": "ts-node bin.ts",
"try:uninstall": "ts-node bin.ts --uninstall",
"test:watch": "jest --watch"
Expand Down
Loading