@sentry/wizard 3.38.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -1
- package/README.md +3 -3
- package/dist/e2e-tests/tests/flutter.test.d.ts +1 -0
- package/dist/e2e-tests/tests/flutter.test.js +190 -0
- package/dist/e2e-tests/tests/flutter.test.js.map +1 -0
- package/dist/e2e-tests/tests/nextjs.test.js +1 -1
- package/dist/e2e-tests/tests/nextjs.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-3.test.js +1 -1
- package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-4.test.js +1 -1
- package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
- package/dist/e2e-tests/tests/remix.test.js +1 -2
- package/dist/e2e-tests/tests/remix.test.js.map +1 -1
- package/dist/e2e-tests/tests/sveltekit.test.js +17 -5
- package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
- package/dist/e2e-tests/utils/index.d.ts +22 -1
- package/dist/e2e-tests/utils/index.js +58 -3
- package/dist/e2e-tests/utils/index.js.map +1 -1
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/apple/apple-wizard.js +1 -1
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +4 -4
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/flutter/code-tools.d.ts +17 -0
- package/dist/src/flutter/code-tools.js +263 -0
- package/dist/src/flutter/code-tools.js.map +1 -0
- package/dist/src/flutter/flutter-wizard.d.ts +2 -0
- package/dist/src/flutter/flutter-wizard.js +171 -0
- package/dist/src/flutter/flutter-wizard.js.map +1 -0
- package/dist/src/flutter/templates.d.ts +9 -0
- package/dist/src/flutter/templates.js +40 -0
- package/dist/src/flutter/templates.js.map +1 -0
- package/dist/src/nextjs/nextjs-wizard.js +3 -1
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/run.d.ts +1 -1
- package/dist/src/run.js +39 -32
- package/dist/src/run.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +2 -3
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/telemetry.d.ts +2 -1
- package/dist/src/telemetry.js +1 -1
- package/dist/src/telemetry.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +1 -1
- package/dist/src/utils/clack-utils.js +3 -3
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/src/utils/package-manager.d.ts +0 -1
- package/dist/src/utils/package-manager.js +9 -10
- package/dist/src/utils/package-manager.js.map +1 -1
- package/dist/test/flutter/code-tools.test.d.ts +1 -0
- package/dist/test/flutter/code-tools.test.js +84 -0
- package/dist/test/flutter/code-tools.test.js.map +1 -0
- package/dist/test/flutter/templates.test.d.ts +1 -0
- package/dist/test/flutter/templates.test.js +41 -0
- package/dist/test/flutter/templates.test.js.map +1 -0
- package/e2e-tests/README.md +5 -1
- package/e2e-tests/test-applications/flutter-test-app/.metadata +45 -0
- package/e2e-tests/test-applications/flutter-test-app/README.md +16 -0
- package/e2e-tests/test-applications/flutter-test-app/analysis_options.yaml +28 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/build.gradle +44 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/AndroidManifest.xml +45 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/kotlin/com/example/flutter_magic/MainActivity.kt +5 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/drawable/launch_background.xml +12 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/values/styles.xml +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/values-night/styles.xml +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/profile/AndroidManifest.xml +7 -0
- package/e2e-tests/test-applications/flutter-test-app/android/build.gradle +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/e2e-tests/test-applications/flutter-test-app/android/gradle.properties +3 -0
- package/e2e-tests/test-applications/flutter-test-app/android/settings.gradle +25 -0
- package/e2e-tests/test-applications/flutter-test-app/lib/main.dart +125 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/CMakeLists.txt +145 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/CMakeLists.txt +88 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugin_registrant.cc +11 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugin_registrant.h +15 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugins.cmake +23 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/main.cc +6 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/my_application.cc +124 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/my_application.h +18 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/Flutter-Release.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/GeneratedPluginRegistrant.swift +10 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Podfile +43 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/AppDelegate.swift +9 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Base.lproj/MainMenu.xib +343 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Debug.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Release.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Warnings.xcconfig +13 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/DebugProfile.entitlements +12 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Info.plist +32 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/MainFlutterWindow.swift +15 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Release.entitlements +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/project.pbxproj +705 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +98 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcworkspace/contents.xcworkspacedata +7 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/RunnerTests/RunnerTests.swift +12 -0
- package/e2e-tests/test-applications/flutter-test-app/pubspec.lock +213 -0
- package/e2e-tests/test-applications/flutter-test-app/pubspec.yaml +89 -0
- package/e2e-tests/test-applications/flutter-test-app/test/widget_test.dart +30 -0
- package/e2e-tests/test-applications/flutter-test-app/web/favicon.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-192.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-maskable-192.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-maskable-512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/index.html +38 -0
- package/e2e-tests/test-applications/flutter-test-app/web/manifest.json +35 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/CMakeLists.txt +108 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/CMakeLists.txt +109 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugin_registrant.cc +11 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugin_registrant.h +15 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugins.cmake +23 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/CMakeLists.txt +40 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/Runner.rc +121 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/flutter_window.cpp +71 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/flutter_window.h +33 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/main.cpp +43 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/resource.h +16 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/resources/app_icon.ico +0 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/runner.exe.manifest +14 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/utils.cpp +65 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/utils.h +19 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/win32_window.cpp +288 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/win32_window.h +102 -0
- package/e2e-tests/test-applications/nextjs-test-app/package.json +1 -1
- package/e2e-tests/tests/flutter.test.ts +127 -0
- package/e2e-tests/tests/nextjs.test.ts +1 -1
- package/e2e-tests/tests/nuxt-3.test.ts +1 -1
- package/e2e-tests/tests/nuxt-4.test.ts +1 -1
- package/e2e-tests/tests/remix.test.ts +30 -19
- package/e2e-tests/tests/sveltekit.test.ts +79 -50
- package/e2e-tests/utils/index.ts +62 -2
- package/lib/Constants.ts +5 -0
- package/package.json +1 -1
- package/src/apple/apple-wizard.ts +1 -1
- package/src/apple/xcode-manager.ts +5 -5
- package/src/flutter/code-tools.ts +284 -0
- package/src/flutter/flutter-wizard.ts +164 -0
- package/src/flutter/templates.ts +90 -0
- package/src/nextjs/nextjs-wizard.ts +4 -1
- package/src/run.ts +7 -0
- package/src/sourcemaps/sourcemaps-wizard.ts +3 -7
- package/src/telemetry.ts +6 -2
- package/src/utils/clack-utils.ts +8 -5
- package/src/utils/package-manager.ts +8 -11
- package/test/flutter/code-tools.test.ts +212 -0
- package/test/flutter/templates.test.ts +100 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { WizardOptions } from '../utils/types';
|
|
2
|
+
import * as Sentry from '@sentry/node';
|
|
3
|
+
import * as codetools from './code-tools';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { showCopyPasteInstructions } from '../utils/clack-utils';
|
|
7
|
+
import { pubspecSnippetColored, initSnippetColored } from './templates';
|
|
8
|
+
import { fetchSdkVersion } from '../utils/release-registry';
|
|
9
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
10
|
+
import * as clack from '@clack/prompts';
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
confirmContinueIfNoOrDirtyGitRepo,
|
|
15
|
+
getOrAskForProjectData,
|
|
16
|
+
printWelcome,
|
|
17
|
+
} from '../utils/clack-utils';
|
|
18
|
+
|
|
19
|
+
import { traceStep, withTelemetry } from '../telemetry';
|
|
20
|
+
import { findFile } from './code-tools';
|
|
21
|
+
|
|
22
|
+
export async function runFlutterWizard(options: WizardOptions): Promise<void> {
|
|
23
|
+
return withTelemetry(
|
|
24
|
+
{
|
|
25
|
+
enabled: options.telemetryEnabled,
|
|
26
|
+
integration: 'flutter',
|
|
27
|
+
wizardOptions: options,
|
|
28
|
+
},
|
|
29
|
+
() => runFlutterWizardWithTelemetry(options),
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function runFlutterWizardWithTelemetry(
|
|
34
|
+
options: WizardOptions,
|
|
35
|
+
): Promise<void> {
|
|
36
|
+
printWelcome({
|
|
37
|
+
wizardName: 'Sentry Flutter Wizard',
|
|
38
|
+
promoCode: options.promoCode,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await confirmContinueIfNoOrDirtyGitRepo();
|
|
42
|
+
|
|
43
|
+
const { selectedProject, selfHosted, sentryUrl, authToken } =
|
|
44
|
+
await getOrAskForProjectData(options, 'flutter');
|
|
45
|
+
|
|
46
|
+
const projectDir = process.cwd();
|
|
47
|
+
const pubspecFile = path.join(projectDir, 'pubspec.yaml');
|
|
48
|
+
if (!fs.existsSync(pubspecFile)) {
|
|
49
|
+
clack.log.error(
|
|
50
|
+
`Could not find ${chalk.cyan(
|
|
51
|
+
'pubspec.yaml',
|
|
52
|
+
)}. Make sure you run the wizard in the projects root folder.`,
|
|
53
|
+
);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ======== STEP 1. Add sentry_flutter and sentry_dart_plugin to pubspec.yaml ============
|
|
58
|
+
|
|
59
|
+
clack.log.step(
|
|
60
|
+
`Adding ${chalk.bold('Sentry')} to your apps ${chalk.cyan(
|
|
61
|
+
'pubspec.yaml',
|
|
62
|
+
)} file.`,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const flutterVersion = await fetchSdkVersion('sentry.dart.flutter');
|
|
66
|
+
const flutterVersionOrAny = flutterVersion ? `^${flutterVersion}` : 'any';
|
|
67
|
+
|
|
68
|
+
const pluginVersion = await fetchSdkVersion('sentry.dart.plugin');
|
|
69
|
+
const pluginVersionOrAny = pluginVersion ? `^${pluginVersion}` : 'any';
|
|
70
|
+
|
|
71
|
+
const pubspecPatched = traceStep('Patch pubspec.yaml', () =>
|
|
72
|
+
codetools.patchPubspec(
|
|
73
|
+
pubspecFile,
|
|
74
|
+
flutterVersionOrAny,
|
|
75
|
+
pluginVersionOrAny,
|
|
76
|
+
selectedProject.slug,
|
|
77
|
+
selectedProject.organization.slug,
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
if (!pubspecPatched) {
|
|
81
|
+
clack.log.warn(
|
|
82
|
+
`Could not patch ${chalk.cyan(
|
|
83
|
+
'pubspec.yaml',
|
|
84
|
+
)}. Add the dependencies to it.`,
|
|
85
|
+
);
|
|
86
|
+
await showCopyPasteInstructions(
|
|
87
|
+
'pubspec.yaml',
|
|
88
|
+
pubspecSnippetColored(
|
|
89
|
+
flutterVersionOrAny,
|
|
90
|
+
pluginVersionOrAny,
|
|
91
|
+
selectedProject.slug,
|
|
92
|
+
selectedProject.organization.slug,
|
|
93
|
+
),
|
|
94
|
+
'This ensures the Sentry SDK and plugin can be imported.',
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
Sentry.setTag('pubspec-patched', pubspecPatched);
|
|
98
|
+
|
|
99
|
+
// ======== STEP 2. Add sentry.properties with auth token ============
|
|
100
|
+
|
|
101
|
+
const propertiesAdded = traceStep('Add sentry.properties', () =>
|
|
102
|
+
codetools.addProperties(pubspecFile, authToken),
|
|
103
|
+
);
|
|
104
|
+
if (!propertiesAdded) {
|
|
105
|
+
clack.log.warn(
|
|
106
|
+
`We could not add ${chalk.cyan(
|
|
107
|
+
'sentry.properties',
|
|
108
|
+
)} file in your project directory in order to provide an auth token for Sentry CLI. You'll have to add it manually, or you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.`,
|
|
109
|
+
);
|
|
110
|
+
} else {
|
|
111
|
+
clack.log.info(
|
|
112
|
+
`We created ${chalk.cyan(
|
|
113
|
+
'sentry.properties',
|
|
114
|
+
)} file in your project directory in order to provide an auth token for Sentry CLI.\nIt was also added to your ".gitignore" file.\nAt your CI enviroment, you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
Sentry.setTag('sentry-properties-added', pubspecPatched);
|
|
118
|
+
|
|
119
|
+
// ======== STEP 3. Patch main.dart with setup and a test error snippet ============
|
|
120
|
+
|
|
121
|
+
clack.log.step(
|
|
122
|
+
`Patching ${chalk.cyan('main.dart')} with setup and test error snippet.`,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const mainFile = findFile(`${projectDir}/lib`, 'main.dart');
|
|
126
|
+
const dsn = selectedProject.keys[0].dsn.public;
|
|
127
|
+
const canEnableProfiling =
|
|
128
|
+
fs.existsSync(`${projectDir}/ios`) || fs.existsSync(`${projectDir}/macos`);
|
|
129
|
+
|
|
130
|
+
const mainPatched = await traceStep('Patch main.dart', () =>
|
|
131
|
+
codetools.patchMain(mainFile, dsn, canEnableProfiling),
|
|
132
|
+
);
|
|
133
|
+
if (!mainPatched) {
|
|
134
|
+
clack.log.warn(
|
|
135
|
+
`Could not patch ${chalk.cyan(
|
|
136
|
+
'main.dart',
|
|
137
|
+
)} file. Place the following code snippet within the apps main function.`,
|
|
138
|
+
);
|
|
139
|
+
await showCopyPasteInstructions(
|
|
140
|
+
'main.dart',
|
|
141
|
+
initSnippetColored(dsn),
|
|
142
|
+
'This ensures the Sentry SDK is ready to capture errors.',
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
Sentry.setTag('main-patched', mainPatched);
|
|
146
|
+
|
|
147
|
+
// ======== OUTRO ========
|
|
148
|
+
|
|
149
|
+
const issuesPageLink = selfHosted
|
|
150
|
+
? `${sentryUrl}organizations/${selectedProject.organization.slug}/issues/?project=${selectedProject.id}`
|
|
151
|
+
: `https://${selectedProject.organization.slug}.sentry.io/issues/?project=${selectedProject.id}`;
|
|
152
|
+
|
|
153
|
+
clack.outro(`
|
|
154
|
+
${chalk.greenBright('Successfully installed the Sentry Flutter SDK!')}
|
|
155
|
+
|
|
156
|
+
${chalk.cyan(
|
|
157
|
+
`You can validate your setup by launching your application and checking Sentry issues page afterwards
|
|
158
|
+
${issuesPageLink}`,
|
|
159
|
+
)}
|
|
160
|
+
|
|
161
|
+
Check out the SDK documentation for further configuration:
|
|
162
|
+
https://docs.sentry.io/platforms/flutter/
|
|
163
|
+
`);
|
|
164
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { makeCodeSnippet } from '../utils/clack-utils';
|
|
2
|
+
|
|
3
|
+
export const sentryImport = `import 'package:sentry_flutter/sentry_flutter.dart';\n`;
|
|
4
|
+
|
|
5
|
+
export function pubspecOptions(project: string, org: string): string {
|
|
6
|
+
return `sentry:
|
|
7
|
+
upload_debug_symbols: true
|
|
8
|
+
upload_source_maps: true
|
|
9
|
+
project: ${project}
|
|
10
|
+
org: ${org}
|
|
11
|
+
`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function sentryProperties(authToken: string): string {
|
|
15
|
+
return `auth_token=${authToken}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function initSnippet(
|
|
19
|
+
dsn: string,
|
|
20
|
+
selectedFeaturesMap: {
|
|
21
|
+
tracing: boolean;
|
|
22
|
+
profiling: boolean;
|
|
23
|
+
},
|
|
24
|
+
runApp: string,
|
|
25
|
+
): string {
|
|
26
|
+
let snippet = `await SentryFlutter.init(
|
|
27
|
+
(options) {
|
|
28
|
+
options.dsn = '${dsn}';`;
|
|
29
|
+
|
|
30
|
+
if (selectedFeaturesMap.tracing) {
|
|
31
|
+
snippet += `
|
|
32
|
+
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
|
|
33
|
+
// We recommend adjusting this value in production.
|
|
34
|
+
options.tracesSampleRate = 1.0;`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (selectedFeaturesMap.profiling && selectedFeaturesMap.tracing) {
|
|
38
|
+
snippet += `
|
|
39
|
+
// The sampling rate for profiling is relative to tracesSampleRate
|
|
40
|
+
// Setting to 1.0 will profile 100% of sampled transactions:
|
|
41
|
+
options.profilesSampleRate = 1.0;`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
snippet += `
|
|
45
|
+
},
|
|
46
|
+
appRunner: () => runApp(SentryWidget(child: ${runApp})),
|
|
47
|
+
);
|
|
48
|
+
// TODO: Remove this line after sending the first sample event to sentry.
|
|
49
|
+
await Sentry.captureException(Exception('This is a sample exception.'));`;
|
|
50
|
+
|
|
51
|
+
return snippet;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function pubspecSnippetColored(
|
|
55
|
+
sentryVersion: string,
|
|
56
|
+
pluginVersion: string,
|
|
57
|
+
project: string,
|
|
58
|
+
org: string,
|
|
59
|
+
): string {
|
|
60
|
+
const snippet = `dependencies:
|
|
61
|
+
sentry_flutter: ${sentryVersion}
|
|
62
|
+
|
|
63
|
+
dev_dependencies:
|
|
64
|
+
sentry_dart_plugin: ${pluginVersion}
|
|
65
|
+
|
|
66
|
+
${pubspecOptions(project, org)}`;
|
|
67
|
+
|
|
68
|
+
return makeCodeSnippet(true, (_unchanged, plus, _minus) => {
|
|
69
|
+
return plus(snippet);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function initSnippetColored(dsn: string): string {
|
|
74
|
+
const snippet = `import 'package:sentry_flutter/sentry_flutter.dart';
|
|
75
|
+
|
|
76
|
+
Future<void>main() async {
|
|
77
|
+
await SentryFlutter.init(
|
|
78
|
+
(options) {
|
|
79
|
+
options.dsn = '${dsn}';
|
|
80
|
+
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
|
|
81
|
+
// We recommend adjusting this value in production.
|
|
82
|
+
options.tracesSampleRate = 1.0;
|
|
83
|
+
},
|
|
84
|
+
appRunner: () => runApp(SentryWidget(child: YourApp())),
|
|
85
|
+
)
|
|
86
|
+
}`;
|
|
87
|
+
return makeCodeSnippet(true, (_unchanged, plus, _minus) => {
|
|
88
|
+
return plus(snippet);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -926,7 +926,7 @@ async function createExamplePage(
|
|
|
926
926
|
* It's valuable enough to for users to justify asking the additional question.
|
|
927
927
|
*/
|
|
928
928
|
async function askShouldSetTunnelRoute() {
|
|
929
|
-
return await traceStep('ask-tunnelRoute-option', async () => {
|
|
929
|
+
return await traceStep('ask-tunnelRoute-option', async (span) => {
|
|
930
930
|
const shouldSetTunnelRoute = await abortIfCancelled(
|
|
931
931
|
clack.select({
|
|
932
932
|
message:
|
|
@@ -953,6 +953,9 @@ async function askShouldSetTunnelRoute() {
|
|
|
953
953
|
);
|
|
954
954
|
}
|
|
955
955
|
|
|
956
|
+
span?.setAttribute('tunnelRoute', shouldSetTunnelRoute);
|
|
957
|
+
Sentry.setTag('tunnelRoute', shouldSetTunnelRoute);
|
|
958
|
+
|
|
956
959
|
return shouldSetTunnelRoute;
|
|
957
960
|
});
|
|
958
961
|
}
|
package/src/run.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { runReactNativeWizard } from './react-native/react-native-wizard';
|
|
|
5
5
|
|
|
6
6
|
import { run as legacyRun } from '../lib/Setup';
|
|
7
7
|
import type { PreselectedProject, WizardOptions } from './utils/types';
|
|
8
|
+
import { runFlutterWizard } from './flutter/flutter-wizard';
|
|
8
9
|
import { runAndroidWizard } from './android/android-wizard';
|
|
9
10
|
import { runAppleWizard } from './apple/apple-wizard';
|
|
10
11
|
import { runNextjsWizard } from './nextjs/nextjs-wizard';
|
|
@@ -18,6 +19,7 @@ import type { PackageDotJson } from './utils/package-json';
|
|
|
18
19
|
|
|
19
20
|
type WizardIntegration =
|
|
20
21
|
| 'reactNative'
|
|
22
|
+
| 'flutter'
|
|
21
23
|
| 'ios'
|
|
22
24
|
| 'android'
|
|
23
25
|
| 'cordova'
|
|
@@ -100,6 +102,7 @@ export async function run(argv: Args) {
|
|
|
100
102
|
message: 'What do you want to set up?',
|
|
101
103
|
options: [
|
|
102
104
|
{ value: 'reactNative', label: 'React Native' },
|
|
105
|
+
{ value: 'flutter', label: 'Flutter' },
|
|
103
106
|
{ value: 'ios', label: 'iOS' },
|
|
104
107
|
{ value: 'android', label: 'Android' },
|
|
105
108
|
{ value: 'cordova', label: 'Cordova' },
|
|
@@ -139,6 +142,10 @@ export async function run(argv: Args) {
|
|
|
139
142
|
});
|
|
140
143
|
break;
|
|
141
144
|
|
|
145
|
+
case 'flutter':
|
|
146
|
+
await runFlutterWizard(wizardOptions);
|
|
147
|
+
break;
|
|
148
|
+
|
|
142
149
|
case 'ios':
|
|
143
150
|
await runAppleWizard(wizardOptions);
|
|
144
151
|
break;
|
|
@@ -267,13 +267,9 @@ export async function configureCI(
|
|
|
267
267
|
'create-react-app',
|
|
268
268
|
].includes(selectedTool);
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const authTokenFile =
|
|
274
|
-
isCliBasedFlowTool || usesSentryCliRc
|
|
275
|
-
? SENTRY_CLI_RC_FILE
|
|
276
|
-
: SENTRY_DOT_ENV_FILE;
|
|
270
|
+
const authTokenFile = isCliBasedFlowTool
|
|
271
|
+
? SENTRY_CLI_RC_FILE
|
|
272
|
+
: SENTRY_DOT_ENV_FILE;
|
|
277
273
|
|
|
278
274
|
if (!isUsingCI) {
|
|
279
275
|
clack.log.info(
|
package/src/telemetry.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
setTag,
|
|
10
10
|
startSpan,
|
|
11
11
|
flush,
|
|
12
|
+
Span,
|
|
12
13
|
} from '@sentry/node';
|
|
13
14
|
import packageJson from '../package.json';
|
|
14
15
|
import { WizardOptions } from './utils/types';
|
|
@@ -110,9 +111,12 @@ function createSentryInstance(enabled: boolean, integration: string) {
|
|
|
110
111
|
return { sentryHub: hub, sentryClient: client };
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
export function traceStep<T>(
|
|
114
|
+
export function traceStep<T>(
|
|
115
|
+
step: string,
|
|
116
|
+
callback: (span: Span | undefined) => T,
|
|
117
|
+
): T {
|
|
114
118
|
updateProgress(step);
|
|
115
|
-
return startSpan({ name: step, op: 'wizard.step' }, () => callback());
|
|
119
|
+
return startSpan({ name: step, op: 'wizard.step' }, (span) => callback(span));
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
export function updateProgress(step: string) {
|
package/src/utils/clack-utils.ts
CHANGED
|
@@ -881,7 +881,8 @@ export async function getOrAskForProjectData(
|
|
|
881
881
|
| 'javascript-sveltekit'
|
|
882
882
|
| 'apple-ios'
|
|
883
883
|
| 'android'
|
|
884
|
-
| 'react-native'
|
|
884
|
+
| 'react-native'
|
|
885
|
+
| 'flutter',
|
|
885
886
|
): Promise<{
|
|
886
887
|
sentryUrl: string;
|
|
887
888
|
selfHosted: boolean;
|
|
@@ -1043,7 +1044,8 @@ async function askForWizardLogin(options: {
|
|
|
1043
1044
|
| 'javascript-sveltekit'
|
|
1044
1045
|
| 'apple-ios'
|
|
1045
1046
|
| 'android'
|
|
1046
|
-
| 'react-native'
|
|
1047
|
+
| 'react-native'
|
|
1048
|
+
| 'flutter';
|
|
1047
1049
|
orgSlug?: string;
|
|
1048
1050
|
projectSlug?: string;
|
|
1049
1051
|
}): Promise<WizardProjectData> {
|
|
@@ -1096,9 +1098,10 @@ async function askForWizardLogin(options: {
|
|
|
1096
1098
|
|
|
1097
1099
|
if (!hasSentryAccount) {
|
|
1098
1100
|
loginUrl.searchParams.set('signup', '1');
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if (options.platform) {
|
|
1104
|
+
loginUrl.searchParams.set('project_platform', options.platform);
|
|
1102
1105
|
}
|
|
1103
1106
|
|
|
1104
1107
|
if (options.promoCode) {
|
|
@@ -9,7 +9,6 @@ import { getPackageDotJson, updatePackageDotJson } from './clack-utils';
|
|
|
9
9
|
export interface PackageManager {
|
|
10
10
|
name: string;
|
|
11
11
|
label: string;
|
|
12
|
-
lockFile: string;
|
|
13
12
|
installCommand: string;
|
|
14
13
|
buildCommand: string;
|
|
15
14
|
/* The command that the package manager uses to run a script from package.json */
|
|
@@ -22,12 +21,14 @@ export interface PackageManager {
|
|
|
22
21
|
export const BUN: PackageManager = {
|
|
23
22
|
name: 'bun',
|
|
24
23
|
label: 'Bun',
|
|
25
|
-
lockFile: 'bun.lockb',
|
|
26
24
|
installCommand: 'bun add',
|
|
27
25
|
buildCommand: 'bun run build',
|
|
28
26
|
runScriptCommand: 'bun run',
|
|
29
27
|
flags: '',
|
|
30
|
-
detect: () =>
|
|
28
|
+
detect: () =>
|
|
29
|
+
['bun.lockb', 'bun.lock'].some((lockFile) =>
|
|
30
|
+
fs.existsSync(path.join(process.cwd(), lockFile)),
|
|
31
|
+
),
|
|
31
32
|
addOverride: async (pkgName, pkgVersion): Promise<void> => {
|
|
32
33
|
const packageDotJson = await getPackageDotJson();
|
|
33
34
|
const overrides = packageDotJson.overrides || {};
|
|
@@ -44,7 +45,6 @@ export const BUN: PackageManager = {
|
|
|
44
45
|
export const YARN_V1: PackageManager = {
|
|
45
46
|
name: 'yarn',
|
|
46
47
|
label: 'Yarn V1',
|
|
47
|
-
lockFile: 'yarn.lock',
|
|
48
48
|
installCommand: 'yarn add',
|
|
49
49
|
buildCommand: 'yarn build',
|
|
50
50
|
runScriptCommand: 'yarn',
|
|
@@ -52,7 +52,7 @@ export const YARN_V1: PackageManager = {
|
|
|
52
52
|
detect: () => {
|
|
53
53
|
try {
|
|
54
54
|
return fs
|
|
55
|
-
.readFileSync(path.join(process.cwd(),
|
|
55
|
+
.readFileSync(path.join(process.cwd(), 'yarn.lock'), 'utf-8')
|
|
56
56
|
.slice(0, 500)
|
|
57
57
|
.includes('yarn lockfile v1');
|
|
58
58
|
} catch (e) {
|
|
@@ -76,7 +76,6 @@ export const YARN_V1: PackageManager = {
|
|
|
76
76
|
export const YARN_V2: PackageManager = {
|
|
77
77
|
name: 'yarn',
|
|
78
78
|
label: 'Yarn V2/3/4',
|
|
79
|
-
lockFile: 'yarn.lock',
|
|
80
79
|
installCommand: 'yarn add',
|
|
81
80
|
buildCommand: 'yarn build',
|
|
82
81
|
runScriptCommand: 'yarn',
|
|
@@ -84,7 +83,7 @@ export const YARN_V2: PackageManager = {
|
|
|
84
83
|
detect: () => {
|
|
85
84
|
try {
|
|
86
85
|
return fs
|
|
87
|
-
.readFileSync(path.join(process.cwd(),
|
|
86
|
+
.readFileSync(path.join(process.cwd(), 'yarn.lock'), 'utf-8')
|
|
88
87
|
.slice(0, 500)
|
|
89
88
|
.includes('__metadata');
|
|
90
89
|
} catch (e) {
|
|
@@ -107,12 +106,11 @@ export const YARN_V2: PackageManager = {
|
|
|
107
106
|
export const PNPM: PackageManager = {
|
|
108
107
|
name: 'pnpm',
|
|
109
108
|
label: 'PNPM',
|
|
110
|
-
lockFile: 'pnpm-lock.yaml',
|
|
111
109
|
installCommand: 'pnpm add',
|
|
112
110
|
buildCommand: 'pnpm build',
|
|
113
111
|
runScriptCommand: 'pnpm',
|
|
114
112
|
flags: '--ignore-workspace-root-check',
|
|
115
|
-
detect: () => fs.existsSync(path.join(process.cwd(),
|
|
113
|
+
detect: () => fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml')),
|
|
116
114
|
addOverride: async (pkgName, pkgVersion): Promise<void> => {
|
|
117
115
|
const packageDotJson = await getPackageDotJson();
|
|
118
116
|
const pnpm = packageDotJson.pnpm || {};
|
|
@@ -133,12 +131,11 @@ export const PNPM: PackageManager = {
|
|
|
133
131
|
export const NPM: PackageManager = {
|
|
134
132
|
name: 'npm',
|
|
135
133
|
label: 'NPM',
|
|
136
|
-
lockFile: 'package-lock.json',
|
|
137
134
|
installCommand: 'npm add',
|
|
138
135
|
buildCommand: 'npm run build',
|
|
139
136
|
runScriptCommand: 'npm run',
|
|
140
137
|
flags: '',
|
|
141
|
-
detect: () => fs.existsSync(path.join(process.cwd(),
|
|
138
|
+
detect: () => fs.existsSync(path.join(process.cwd(), 'package-lock.json')),
|
|
142
139
|
addOverride: async (pkgName, pkgVersion): Promise<void> => {
|
|
143
140
|
const packageDotJson = await getPackageDotJson();
|
|
144
141
|
const overrides = packageDotJson.overrides || {};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
//@ts-ignore
|
|
2
|
+
import {
|
|
3
|
+
patchMainContent,
|
|
4
|
+
getDependenciesLocation,
|
|
5
|
+
getDevDependenciesLocation,
|
|
6
|
+
getLastImportLineLocation,
|
|
7
|
+
} from '../../src/flutter/code-tools';
|
|
8
|
+
//@ts-ignore
|
|
9
|
+
import { initSnippet } from '../../src/flutter/templates';
|
|
10
|
+
|
|
11
|
+
describe('code-tools', () => {
|
|
12
|
+
const pubspec = `name: flutter_example
|
|
13
|
+
description: An example flutter app.
|
|
14
|
+
version: 1.0.0
|
|
15
|
+
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|
16
|
+
|
|
17
|
+
environment:
|
|
18
|
+
sdk: '>=2.17.0 <4.0.0'
|
|
19
|
+
flutter: '>=3.0.0'
|
|
20
|
+
|
|
21
|
+
dependencies:
|
|
22
|
+
flutter:
|
|
23
|
+
sdk: flutter
|
|
24
|
+
|
|
25
|
+
dev_dependencies:
|
|
26
|
+
flutter_lints: ^2.0.0
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const simpleRunApp = `import 'package:flutter/widgets.dart';
|
|
30
|
+
|
|
31
|
+
void main() {
|
|
32
|
+
runApp(const MyApp());
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const asyncRunApp = `import 'package:flutter/widgets.dart';
|
|
37
|
+
|
|
38
|
+
void main() {
|
|
39
|
+
runApp(const MyApp());
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const selectedFeaturesMap = {
|
|
44
|
+
tracing: true,
|
|
45
|
+
profiling: true,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const simpleRunAppPatched = `import 'package:flutter/widgets.dart';
|
|
49
|
+
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
50
|
+
|
|
51
|
+
Future<void> main() async {
|
|
52
|
+
${initSnippet('dsn', selectedFeaturesMap, 'const MyApp()')}
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const paramRunApp = `import 'package:flutter/widgets.dart';
|
|
57
|
+
|
|
58
|
+
Future<void> main() async {
|
|
59
|
+
await someFunction();
|
|
60
|
+
runApp(MyApp(param: SomeParam()));
|
|
61
|
+
await anotherFunction();
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
const paramRunAppPatched = `import 'package:flutter/widgets.dart';
|
|
66
|
+
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
67
|
+
|
|
68
|
+
Future<void> main() async {
|
|
69
|
+
await someFunction();
|
|
70
|
+
${initSnippet('dsn', selectedFeaturesMap, 'MyApp(param: SomeParam())')}
|
|
71
|
+
await anotherFunction();
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
const multilineRunApp = `import 'package:flutter/widgets.dart';
|
|
76
|
+
|
|
77
|
+
void main() {
|
|
78
|
+
runApp(
|
|
79
|
+
MyApp(
|
|
80
|
+
param: Param(),
|
|
81
|
+
multi: Another(1),
|
|
82
|
+
line: await bites(the: "dust"),
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
anotherFunction();
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
const multilineRunAppPatched = `import 'package:flutter/widgets.dart';
|
|
90
|
+
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
91
|
+
|
|
92
|
+
Future<void> main() async {
|
|
93
|
+
${initSnippet(
|
|
94
|
+
'dsn',
|
|
95
|
+
selectedFeaturesMap,
|
|
96
|
+
`
|
|
97
|
+
MyApp(
|
|
98
|
+
param: Param(),
|
|
99
|
+
multi: Another(1),
|
|
100
|
+
line: await bites(the: "dust"),
|
|
101
|
+
),
|
|
102
|
+
`,
|
|
103
|
+
)}
|
|
104
|
+
anotherFunction();
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
describe('patchMainContent', () => {
|
|
109
|
+
it('wraps simple runApp', () => {
|
|
110
|
+
expect(patchMainContent('dsn', simpleRunApp, selectedFeaturesMap)).toBe(
|
|
111
|
+
simpleRunAppPatched,
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('wraps async runApp', () => {
|
|
116
|
+
expect(patchMainContent('dsn', asyncRunApp, selectedFeaturesMap)).toBe(
|
|
117
|
+
simpleRunAppPatched,
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('wraps runApp with parameterized app', () => {
|
|
122
|
+
expect(patchMainContent('dsn', paramRunApp, selectedFeaturesMap)).toBe(
|
|
123
|
+
paramRunAppPatched,
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('wraps multiline runApp', () => {
|
|
128
|
+
expect(
|
|
129
|
+
patchMainContent('dsn', multilineRunApp, selectedFeaturesMap),
|
|
130
|
+
).toBe(multilineRunAppPatched);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('pubspec', () => {
|
|
135
|
+
it('returns proper line index for dependencies', () => {
|
|
136
|
+
expect(getDependenciesLocation(pubspec)).toBe(
|
|
137
|
+
pubspec.indexOf(' flutter:\n'),
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('returns proper line index for dev-dependencies', () => {
|
|
142
|
+
expect(getDevDependenciesLocation(pubspec)).toBe(
|
|
143
|
+
pubspec.indexOf(' flutter_lints: ^2.0.0\n'),
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('getLastImportLineLocation', () => {
|
|
149
|
+
it('returns proper line index', () => {
|
|
150
|
+
const code =
|
|
151
|
+
`import 'foo:bar';\n` + `//<insert-location>\n` + `class X {}`;
|
|
152
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
153
|
+
code.indexOf('//<insert-location>'),
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('returns proper line index when alias import is used', () => {
|
|
158
|
+
const code =
|
|
159
|
+
`import 'package:my_library/utils.dart' as utils;\n` +
|
|
160
|
+
`//<insert-location>\n` +
|
|
161
|
+
`class X {}`;
|
|
162
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
163
|
+
code.indexOf('//<insert-location>'),
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('returns proper line index when specific parts import is used', () => {
|
|
168
|
+
const code =
|
|
169
|
+
`import 'dart:math' show pi, sin;\n` +
|
|
170
|
+
`//<insert-location>\n` +
|
|
171
|
+
`class X {}`;
|
|
172
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
173
|
+
code.indexOf('//<insert-location>'),
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('returns proper line index when hide import is used', () => {
|
|
178
|
+
const code =
|
|
179
|
+
`import 'dart:math' hide Random;\n` +
|
|
180
|
+
`//<insert-location>\n` +
|
|
181
|
+
`class X {}`;
|
|
182
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
183
|
+
code.indexOf('//<insert-location>'),
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('returns proper line index when deferred import is used', () => {
|
|
188
|
+
const code =
|
|
189
|
+
`import 'package:my_library/large_library.dart' deferred as largeLibrary;\n` +
|
|
190
|
+
`//<insert-location>\n` +
|
|
191
|
+
`class X {}`;
|
|
192
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
193
|
+
code.indexOf('//<insert-location>'),
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('returns proper line index when multiple imports (with newlines) are present', () => {
|
|
198
|
+
const code =
|
|
199
|
+
`import 'foo:bar';\n` +
|
|
200
|
+
`import 'package:my_library/utils.dart' as utils;\n` +
|
|
201
|
+
`import 'dart:math' show pi, sin;\n` +
|
|
202
|
+
`import 'dart:math' hide Random;\n` +
|
|
203
|
+
`\n` +
|
|
204
|
+
`import 'package:my_library/large_library.dart' deferred as largeLibrary;\n` +
|
|
205
|
+
`//<insert-location>\n` +
|
|
206
|
+
`class X {}`;
|
|
207
|
+
expect(getLastImportLineLocation(code)).toBe(
|
|
208
|
+
code.indexOf('//<insert-location>'),
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|