nativescript 8.1.4 → 8.1.5
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/config/test-dependencies.json +8 -3
- package/config/test-deps-versions-generated.json +1 -1
- package/lib/.d.ts +1 -0
- package/lib/commands/clean.js +7 -2
- package/lib/commands/test-init.js +47 -6
- package/lib/common/dispatchers.js +3 -0
- package/lib/common/services/hooks-service.js +93 -57
- package/lib/controllers/migrate-controller.js +56 -7
- package/lib/definitions/project.d.ts +9 -3
- package/lib/package-manager.js +12 -1
- package/lib/services/project-cleanup-service.js +20 -5
- package/lib/services/project-config-service.js +5 -1
- package/lib/services/test-execution-service.js +1 -0
- package/package.json +1 -1
- package/resources/test/karma.conf.js +15 -38
- package/resources/test/test-main.js +9 -0
- package/resources/test/test-main.ts +11 -0
- package/resources/test/tsconfig.spec.json +9 -0
- package/lib/common/.vscode/settings.json +0 -9
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"name": "@jsdevtools/coverage-istanbul-loader"
|
|
4
|
+
},
|
|
2
5
|
{
|
|
3
6
|
"name": "karma"
|
|
4
7
|
},
|
|
5
8
|
{
|
|
6
|
-
"name": "karma-
|
|
9
|
+
"name": "karma-coverage"
|
|
7
10
|
},
|
|
8
11
|
{
|
|
9
|
-
"name": "karma-
|
|
10
|
-
"excludedPeerDependencies": ["webpack"]
|
|
12
|
+
"name": "karma-nativescript-launcher"
|
|
11
13
|
},
|
|
12
14
|
{
|
|
13
15
|
"name": "mocha",
|
|
@@ -48,5 +50,8 @@
|
|
|
48
50
|
"name": "@types/qunit",
|
|
49
51
|
"framework": "qunit",
|
|
50
52
|
"projectType": ".ts"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "nyc"
|
|
51
56
|
}
|
|
52
57
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"karma":"6.3.
|
|
1
|
+
{"@jsdevtools/coverage-istanbul-loader":"3.0.5","karma":"6.3.9","karma-coverage":"2.0.3","karma-nativescript-launcher":"0.4.0","mocha":"9.1.3","karma-mocha":"2.0.1","karma-chai":"0.1.0","karma-jasmine":"4.0.1","karma-qunit":"4.1.2","@types/karma-chai":"0.1.2","@types/mocha":"9.0.0","@types/jasmine":"3.10.2","@types/qunit":"2.11.2","nyc":"15.1.0"}
|
package/lib/.d.ts
CHANGED
|
@@ -217,6 +217,7 @@
|
|
|
217
217
|
/// <reference path="common/test/unit-tests/project-files-provider-base.ts" />
|
|
218
218
|
/// <reference path="common/test/unit-tests/services/files-hash-service.ts" />
|
|
219
219
|
/// <reference path="common/test/unit-tests/services/help-service.ts" />
|
|
220
|
+
/// <reference path="common/test/unit-tests/services/hook-service.ts" />
|
|
220
221
|
/// <reference path="common/test/unit-tests/services/json-file-settings-service.ts" />
|
|
221
222
|
/// <reference path="common/test/unit-tests/services/net-service.ts" />
|
|
222
223
|
/// <reference path="common/test/unit-tests/services/settings-service.ts" />
|
package/lib/commands/clean.js
CHANGED
|
@@ -37,8 +37,13 @@ class CleanCommand {
|
|
|
37
37
|
}
|
|
38
38
|
catch (err) {
|
|
39
39
|
}
|
|
40
|
-
yield this.$projectCleanupService.clean(pathsToClean);
|
|
41
|
-
|
|
40
|
+
const success = yield this.$projectCleanupService.clean(pathsToClean);
|
|
41
|
+
if (success) {
|
|
42
|
+
spinner.succeed("Project successfully cleaned.");
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
spinner.fail(`${"Project unsuccessfully cleaned.".red}`);
|
|
46
|
+
}
|
|
42
47
|
});
|
|
43
48
|
}
|
|
44
49
|
}
|
|
@@ -91,12 +91,19 @@ class TestInitCommand {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
yield this.$pluginsService.add("@nativescript/unit-test-runner", this.$projectData);
|
|
94
|
+
this.$logger.clearScreen();
|
|
95
|
+
const bufferedLogs = [];
|
|
94
96
|
const testsDir = path.join(this.$projectData.appDirectoryPath, "tests");
|
|
95
97
|
const projectTestsDir = path.relative(this.$projectData.projectDir, testsDir);
|
|
96
98
|
const relativeTestsDir = path.relative(this.$projectData.appDirectoryPath, testsDir);
|
|
97
99
|
let shouldCreateSampleTests = true;
|
|
98
100
|
if (this.$fs.exists(testsDir)) {
|
|
99
|
-
|
|
101
|
+
const specFilenamePattern = `<filename>.spec${projectFilesExtension}`;
|
|
102
|
+
bufferedLogs.push([
|
|
103
|
+
`Note: The "${projectTestsDir}" directory already exists, will not create example tests in the project.`,
|
|
104
|
+
`You may create "${specFilenamePattern}" files anywhere you'd like.`,
|
|
105
|
+
"",
|
|
106
|
+
].join("\n").yellow);
|
|
100
107
|
shouldCreateSampleTests = false;
|
|
101
108
|
}
|
|
102
109
|
this.$fs.ensureDirectoryExists(testsDir);
|
|
@@ -113,14 +120,48 @@ class TestInitCommand {
|
|
|
113
120
|
});
|
|
114
121
|
this.$fs.writeFile(path.join(projectDir, "karma.conf.js"), karmaConf);
|
|
115
122
|
const exampleFilePath = this.$resources.resolvePath(`test/example.${frameworkToInstall}${projectFilesExtension}`);
|
|
123
|
+
const targetExampleTestPath = path.join(testsDir, `example.spec${projectFilesExtension}`);
|
|
116
124
|
if (shouldCreateSampleTests && this.$fs.exists(exampleFilePath)) {
|
|
117
|
-
this.$fs.copyFile(exampleFilePath,
|
|
118
|
-
|
|
125
|
+
this.$fs.copyFile(exampleFilePath, targetExampleTestPath);
|
|
126
|
+
const targetExampleTestRelativePath = path.relative(projectDir, targetExampleTestPath);
|
|
127
|
+
bufferedLogs.push(`Added example test: ${targetExampleTestRelativePath.yellow}`);
|
|
119
128
|
}
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
const testMainResourcesPath = this.$resources.resolvePath(`test/test-main${projectFilesExtension}`);
|
|
130
|
+
const testMainPath = path.join(this.$projectData.appDirectoryPath, `test${projectFilesExtension}`);
|
|
131
|
+
if (!this.$fs.exists(testMainPath)) {
|
|
132
|
+
this.$fs.copyFile(testMainResourcesPath, testMainPath);
|
|
133
|
+
const testMainRelativePath = path.relative(projectDir, testMainPath);
|
|
134
|
+
bufferedLogs.push(`Main test entrypoint created: ${testMainRelativePath.yellow}`);
|
|
122
135
|
}
|
|
123
|
-
this.$
|
|
136
|
+
const testTsConfigTemplate = this.$resources.readText("test/tsconfig.spec.json");
|
|
137
|
+
const testTsConfig = _.template(testTsConfigTemplate)({
|
|
138
|
+
basePath: this.$projectData.getAppDirectoryRelativePath(),
|
|
139
|
+
});
|
|
140
|
+
this.$fs.writeFile(path.join(projectDir, "tsconfig.spec.json"), testTsConfig);
|
|
141
|
+
bufferedLogs.push(`Added/replaced ${"tsconfig.spec.json".yellow}`);
|
|
142
|
+
const greyDollarSign = "$".grey;
|
|
143
|
+
this.$logger.info([
|
|
144
|
+
[
|
|
145
|
+
`Tests using`.green,
|
|
146
|
+
frameworkToInstall.cyan,
|
|
147
|
+
`were successfully initialized.`.green,
|
|
148
|
+
].join(" "),
|
|
149
|
+
"",
|
|
150
|
+
...bufferedLogs,
|
|
151
|
+
"",
|
|
152
|
+
`Note: @nativescript/unit-test-runner was included in "dependencies" as a convenience to automatically adjust your app's Info.plist on iOS and AndroidManifest.xml on Android to ensure the socket connects properly.`
|
|
153
|
+
.yellow,
|
|
154
|
+
"",
|
|
155
|
+
`For production you may want to move to "devDependencies" and manage the settings yourself.`
|
|
156
|
+
.yellow,
|
|
157
|
+
"",
|
|
158
|
+
"",
|
|
159
|
+
`You can now run your tests:`,
|
|
160
|
+
"",
|
|
161
|
+
` ${greyDollarSign} ${"ns test ios".green}`,
|
|
162
|
+
` ${greyDollarSign} ${"ns test android".green}`,
|
|
163
|
+
"",
|
|
164
|
+
].join("\n"));
|
|
124
165
|
});
|
|
125
166
|
}
|
|
126
167
|
}
|
|
@@ -91,6 +91,9 @@ class CommandDispatcher {
|
|
|
91
91
|
printVersion() {
|
|
92
92
|
return __awaiter(this, void 0, void 0, function* () {
|
|
93
93
|
this.$logger.info(this.$staticConfig.version);
|
|
94
|
+
if (this.$options.json) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
94
97
|
const spinner = this.$terminalSpinnerService.createSpinner();
|
|
95
98
|
spinner.start("Checking for updates...");
|
|
96
99
|
const nativescriptCliVersion = yield this.$versionsService.getNativescriptCliVersion();
|
|
@@ -23,7 +23,7 @@ class Hook {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
class HooksService {
|
|
26
|
-
constructor($childProcess, $fs, $logger, $errors, $config, $staticConfig, $injector, $projectHelper, $options, $performanceService) {
|
|
26
|
+
constructor($childProcess, $fs, $logger, $errors, $config, $staticConfig, $injector, $projectHelper, $options, $performanceService, $projectConfigService) {
|
|
27
27
|
this.$childProcess = $childProcess;
|
|
28
28
|
this.$fs = $fs;
|
|
29
29
|
this.$logger = $logger;
|
|
@@ -34,6 +34,7 @@ class HooksService {
|
|
|
34
34
|
this.$projectHelper = $projectHelper;
|
|
35
35
|
this.$options = $options;
|
|
36
36
|
this.$performanceService = $performanceService;
|
|
37
|
+
this.$projectConfigService = $projectConfigService;
|
|
37
38
|
}
|
|
38
39
|
get hookArgsName() {
|
|
39
40
|
return "hookArgs";
|
|
@@ -46,6 +47,10 @@ class HooksService {
|
|
|
46
47
|
this.hooksDirectories.push(path.join(projectDir, HooksService.HOOKS_DIRECTORY_NAME));
|
|
47
48
|
}
|
|
48
49
|
this.$logger.trace("Hooks directories: " + util.inspect(this.hooksDirectories));
|
|
50
|
+
const customHooks = this.$projectConfigService.getValue("hooks", []);
|
|
51
|
+
if (customHooks.length) {
|
|
52
|
+
this.$logger.trace("Custom hooks: " + util.inspect(customHooks));
|
|
53
|
+
}
|
|
49
54
|
}
|
|
50
55
|
static formatHookName(commandName) {
|
|
51
56
|
return commandName.replace(/\|[\s\S]*$/, "");
|
|
@@ -79,6 +84,10 @@ class HooksService {
|
|
|
79
84
|
for (const hooksDirectory of this.hooksDirectories) {
|
|
80
85
|
results.push(yield this.executeHooksInDirectory(hooksDirectory, hookName, hookArguments));
|
|
81
86
|
}
|
|
87
|
+
const customHooks = this.getCustomHooksByName(hookName);
|
|
88
|
+
for (const hook of customHooks) {
|
|
89
|
+
results.push(yield this.executeHook(this.$projectHelper.projectDir, hookName, hook, hookArguments));
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
92
|
catch (err) {
|
|
84
93
|
this.$logger.trace(`Failed during hook execution ${hookName}.`);
|
|
@@ -87,75 +96,102 @@ class HooksService {
|
|
|
87
96
|
return _.flatten(results);
|
|
88
97
|
});
|
|
89
98
|
}
|
|
90
|
-
|
|
99
|
+
executeHook(directoryPath, hookName, hook, hookArguments) {
|
|
91
100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
92
101
|
hookArguments = hookArguments || {};
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (path.extname(hook.fullPath).toLowerCase() === ".js") {
|
|
104
|
-
command = process.argv[0];
|
|
105
|
-
inProc = this.shouldExecuteInProcess(this.$fs.readText(hook.fullPath));
|
|
106
|
-
}
|
|
102
|
+
let result;
|
|
103
|
+
const relativePath = path.relative(directoryPath, hook.fullPath);
|
|
104
|
+
const trackId = relativePath.replace(new RegExp("\\" + path.sep, "g"), constants_1.AnalyticsEventLabelDelimiter);
|
|
105
|
+
let command = this.getSheBangInterpreter(hook);
|
|
106
|
+
let inProc = false;
|
|
107
|
+
if (!command) {
|
|
108
|
+
command = hook.fullPath;
|
|
109
|
+
if (path.extname(hook.fullPath).toLowerCase() === ".js") {
|
|
110
|
+
command = process.argv[0];
|
|
111
|
+
inProc = this.shouldExecuteInProcess(this.$fs.readText(hook.fullPath));
|
|
107
112
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
}
|
|
114
|
+
const startTime = this.$performanceService.now();
|
|
115
|
+
if (inProc) {
|
|
116
|
+
this.$logger.trace("Executing %s hook at location %s in-process", hookName, hook.fullPath);
|
|
117
|
+
const hookEntryPoint = require(hook.fullPath);
|
|
118
|
+
this.$logger.trace(`Validating ${hookName} arguments.`);
|
|
119
|
+
const invalidArguments = this.validateHookArguments(hookEntryPoint, hook.fullPath);
|
|
120
|
+
if (invalidArguments.length) {
|
|
121
|
+
this.$logger.warn(`${hook.fullPath} will NOT be executed because it has invalid arguments - ${invalidArguments.join(", ").grey}.`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const projectDataHookArg = hookArguments["hookArgs"] && hookArguments["hookArgs"]["projectData"];
|
|
125
|
+
if (projectDataHookArg) {
|
|
126
|
+
hookArguments["projectData"] = hookArguments["$projectData"] = projectDataHookArg;
|
|
127
|
+
}
|
|
128
|
+
const maybePromise = this.$injector.resolve(hookEntryPoint, hookArguments);
|
|
129
|
+
if (maybePromise) {
|
|
130
|
+
this.$logger.trace("Hook promises to signal completion");
|
|
131
|
+
try {
|
|
132
|
+
result = yield maybePromise;
|
|
121
133
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
results.push(result);
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err &&
|
|
136
|
+
_.isBoolean(err.stopExecution) &&
|
|
137
|
+
err.errorAsWarning === true) {
|
|
138
|
+
this.$logger.warn(err.message || err);
|
|
128
139
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
err.errorAsWarning === true) {
|
|
133
|
-
this.$logger.warn(err.message || err);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
this.$logger.error(err);
|
|
137
|
-
throw (err || new Error(`Failed to execute hook: ${hook.fullPath}.`));
|
|
138
|
-
}
|
|
140
|
+
else {
|
|
141
|
+
this.$logger.error(err);
|
|
142
|
+
throw err || new Error(`Failed to execute hook: ${hook.fullPath}.`);
|
|
139
143
|
}
|
|
140
|
-
this.$logger.trace("Hook completed");
|
|
141
144
|
}
|
|
145
|
+
this.$logger.trace("Hook completed");
|
|
142
146
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const environment = this.prepareEnvironment(hook.fullPath);
|
|
150
|
+
this.$logger.trace("Executing %s hook at location %s with environment ", hookName, hook.fullPath, environment);
|
|
151
|
+
const output = yield this.$childProcess.spawnFromEvent(command, [hook.fullPath], "close", environment, { throwError: false });
|
|
152
|
+
result = output;
|
|
153
|
+
if (output.exitCode !== 0) {
|
|
154
|
+
throw new Error(output.stdout + output.stderr);
|
|
155
|
+
}
|
|
156
|
+
this.$logger.trace("Finished executing %s hook at location %s with environment ", hookName, hook.fullPath, environment);
|
|
157
|
+
}
|
|
158
|
+
const endTime = this.$performanceService.now();
|
|
159
|
+
this.$performanceService.processExecutionData(trackId, startTime, endTime, [
|
|
160
|
+
hookArguments,
|
|
161
|
+
]);
|
|
162
|
+
return result;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
executeHooksInDirectory(directoryPath, hookName, hookArguments) {
|
|
166
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
167
|
+
hookArguments = hookArguments || {};
|
|
168
|
+
const results = [];
|
|
169
|
+
const hooks = this.getHooksByName(directoryPath, hookName);
|
|
170
|
+
for (let i = 0; i < hooks.length; ++i) {
|
|
171
|
+
const hook = hooks[i];
|
|
172
|
+
const result = yield this.executeHook(directoryPath, hookName, hook, hookArguments);
|
|
173
|
+
if (result) {
|
|
174
|
+
results.push(result);
|
|
152
175
|
}
|
|
153
|
-
const endTime = this.$performanceService.now();
|
|
154
|
-
this.$performanceService.processExecutionData(trackId, startTime, endTime, [hookArguments]);
|
|
155
176
|
}
|
|
156
177
|
return results;
|
|
157
178
|
});
|
|
158
179
|
}
|
|
180
|
+
getCustomHooksByName(hookName) {
|
|
181
|
+
const hooks = [];
|
|
182
|
+
const customHooks = this.$projectConfigService.getValue("hooks", []);
|
|
183
|
+
for (const cHook of customHooks) {
|
|
184
|
+
if (cHook.type === hookName) {
|
|
185
|
+
const fullPath = path.join(this.$projectHelper.projectDir, cHook.script);
|
|
186
|
+
const isFile = this.$fs.getFsStats(fullPath).isFile();
|
|
187
|
+
if (isFile) {
|
|
188
|
+
const fileNameParts = cHook.script.split("/");
|
|
189
|
+
hooks.push(new Hook(this.getBaseFilename(fileNameParts[fileNameParts.length - 1]), fullPath));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return hooks;
|
|
194
|
+
}
|
|
159
195
|
getHooksByName(directoryPath, hookName) {
|
|
160
196
|
const allBaseHooks = this.getHooksInDirectory(directoryPath);
|
|
161
197
|
const baseHooks = _.filter(allBaseHooks, (hook) => hook.name.toLowerCase() === hookName.toLowerCase());
|
|
@@ -19,6 +19,7 @@ const simple_git_1 = require("simple-git");
|
|
|
19
19
|
const update_controller_base_1 = require("./update-controller-base");
|
|
20
20
|
const helpers_1 = require("../common/helpers");
|
|
21
21
|
const yok_1 = require("../common/yok");
|
|
22
|
+
const temp = require("temp");
|
|
22
23
|
class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
23
24
|
constructor($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager, $pacoteService, $logger, $errors, $pluginsService, $projectDataService, $projectConfigService, $options, $resources, $injector, $settingsService, $staticConfig, $terminalSpinnerService, $projectCleanupService, $projectBackupService, $childProcess) {
|
|
24
25
|
super($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager, $pacoteService);
|
|
@@ -150,7 +151,7 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
150
151
|
{
|
|
151
152
|
packageName: "@nativescript/unit-test-runner",
|
|
152
153
|
minVersion: "1.0.0",
|
|
153
|
-
desiredVersion: "~
|
|
154
|
+
desiredVersion: "~3.0.0",
|
|
154
155
|
shouldMigrateAction(dependency, projectData, loose) {
|
|
155
156
|
return __awaiter(this, void 0, void 0, function* () {
|
|
156
157
|
if (!this.hasDependency(dependency, projectData)) {
|
|
@@ -289,10 +290,21 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
289
290
|
this.spinner.info("Updating project dependencies");
|
|
290
291
|
yield this.migrateDependencies(projectData, platforms, loose);
|
|
291
292
|
this.spinner.succeed("Project dependencies have been updated");
|
|
293
|
+
const isAngular = this.hasDependency({
|
|
294
|
+
packageName: "@nativescript/angular",
|
|
295
|
+
}, projectData);
|
|
296
|
+
let polyfillsPath;
|
|
297
|
+
if (isAngular) {
|
|
298
|
+
polyfillsPath = yield this.checkOrCreatePolyfillsTS(projectData);
|
|
299
|
+
}
|
|
292
300
|
const tsConfigPath = path.resolve(projectDir, "tsconfig.json");
|
|
293
301
|
if (this.$fs.exists(tsConfigPath)) {
|
|
294
302
|
this.spinner.info(`Updating ${"tsconfig.json".yellow}`);
|
|
295
|
-
yield this.migrateTSConfig(
|
|
303
|
+
yield this.migrateTSConfig({
|
|
304
|
+
tsConfigPath,
|
|
305
|
+
isAngular,
|
|
306
|
+
polyfillsPath,
|
|
307
|
+
});
|
|
296
308
|
this.spinner.succeed(`Updated ${"tsconfig.json".yellow}`);
|
|
297
309
|
}
|
|
298
310
|
yield this.migrateWebpack5(projectDir, projectData);
|
|
@@ -673,10 +685,7 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
673
685
|
const dependencies = [
|
|
674
686
|
{
|
|
675
687
|
packageName: "karma-webpack",
|
|
676
|
-
|
|
677
|
-
desiredVersion: "~5.0.0",
|
|
678
|
-
isDev: true,
|
|
679
|
-
shouldAddIfMissing: true,
|
|
688
|
+
shouldRemove: true,
|
|
680
689
|
},
|
|
681
690
|
{
|
|
682
691
|
packageName: "karma-jasmine",
|
|
@@ -712,7 +721,7 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
712
721
|
return dependencies;
|
|
713
722
|
});
|
|
714
723
|
}
|
|
715
|
-
migrateTSConfig(tsConfigPath) {
|
|
724
|
+
migrateTSConfig({ tsConfigPath, isAngular, polyfillsPath, }) {
|
|
716
725
|
return __awaiter(this, void 0, void 0, function* () {
|
|
717
726
|
try {
|
|
718
727
|
const configContents = this.$fs.readJson(tsConfigPath);
|
|
@@ -725,6 +734,16 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
725
734
|
configContents.compilerOptions.lib = [
|
|
726
735
|
...new Set([...(configContents.compilerOptions.lib || []), "es2017"]),
|
|
727
736
|
];
|
|
737
|
+
if (isAngular) {
|
|
738
|
+
if (configContents.files) {
|
|
739
|
+
configContents.files = [
|
|
740
|
+
...new Set([
|
|
741
|
+
...(configContents.files || []),
|
|
742
|
+
polyfillsPath !== null && polyfillsPath !== void 0 ? polyfillsPath : "./src/polyfills.ts",
|
|
743
|
+
]),
|
|
744
|
+
];
|
|
745
|
+
}
|
|
746
|
+
}
|
|
728
747
|
this.$fs.writeJson(tsConfigPath, configContents);
|
|
729
748
|
return true;
|
|
730
749
|
}
|
|
@@ -734,6 +753,30 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
734
753
|
}
|
|
735
754
|
});
|
|
736
755
|
}
|
|
756
|
+
checkOrCreatePolyfillsTS(projectData) {
|
|
757
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
758
|
+
const { projectDir, appDirectoryPath } = projectData;
|
|
759
|
+
const possiblePaths = [
|
|
760
|
+
`${appDirectoryPath}/polyfills.ts`,
|
|
761
|
+
`./src/polyfills.ts`,
|
|
762
|
+
`./app/polyfills.ts`,
|
|
763
|
+
].map((possiblePath) => path.resolve(projectDir, possiblePath));
|
|
764
|
+
let polyfillsPath = possiblePaths.find((possiblePath) => {
|
|
765
|
+
return this.$fs.exists(possiblePath);
|
|
766
|
+
});
|
|
767
|
+
if (polyfillsPath) {
|
|
768
|
+
return "./" + path.relative(projectDir, polyfillsPath);
|
|
769
|
+
}
|
|
770
|
+
const tempDir = temp.mkdirSync({
|
|
771
|
+
prefix: "migrate-angular-polyfills",
|
|
772
|
+
});
|
|
773
|
+
yield this.$pacoteService.extractPackage(constants.RESERVED_TEMPLATE_NAMES["angular"], tempDir);
|
|
774
|
+
this.$fs.copyFile(path.resolve(tempDir, "src/polyfills.ts"), possiblePaths[0]);
|
|
775
|
+
this.$fs.deleteDirectory(tempDir);
|
|
776
|
+
this.spinner.succeed(`Created fresh ${"polyfills.ts".cyan}`);
|
|
777
|
+
return "./" + path.relative(projectDir, possiblePaths[0]);
|
|
778
|
+
});
|
|
779
|
+
}
|
|
737
780
|
migrateNativeScriptAngular() {
|
|
738
781
|
return __awaiter(this, void 0, void 0, function* () {
|
|
739
782
|
const minVersion = "10.0.0";
|
|
@@ -799,6 +842,12 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
|
|
|
799
842
|
desiredVersion: "~0.11.4",
|
|
800
843
|
shouldAddIfMissing: true,
|
|
801
844
|
},
|
|
845
|
+
{
|
|
846
|
+
packageName: "@angular/cli",
|
|
847
|
+
minVersion,
|
|
848
|
+
desiredVersion,
|
|
849
|
+
isDev: true,
|
|
850
|
+
},
|
|
802
851
|
{
|
|
803
852
|
packageName: "@angular/compiler-cli",
|
|
804
853
|
minVersion,
|
|
@@ -134,6 +134,11 @@ interface INsConfigAndroid extends INsConfigPlaform {
|
|
|
134
134
|
enableMultithreadedJavascript?: boolean;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
interface INsConfigHooks {
|
|
138
|
+
type?: string;
|
|
139
|
+
script: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
137
142
|
interface INsConfig {
|
|
138
143
|
id?: string;
|
|
139
144
|
main?: string;
|
|
@@ -146,6 +151,7 @@ interface INsConfig {
|
|
|
146
151
|
ios?: INsConfigIOS;
|
|
147
152
|
android?: INsConfigAndroid;
|
|
148
153
|
ignoredNativeDependencies?: string[];
|
|
154
|
+
hooks?: INsConfigHooks[];
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
interface IProjectData extends ICreateProjectData {
|
|
@@ -302,13 +308,13 @@ interface IProjectCleanupService {
|
|
|
302
308
|
* Clean multiple paths
|
|
303
309
|
* @param {string[]} pathsToClean
|
|
304
310
|
*/
|
|
305
|
-
clean(pathsToClean: string[]): Promise<
|
|
311
|
+
clean(pathsToClean: string[]): Promise<boolean>;
|
|
306
312
|
|
|
307
313
|
/**
|
|
308
314
|
* Clean a single path
|
|
309
315
|
* @param {string} pathToClean
|
|
310
316
|
*/
|
|
311
|
-
cleanPath(pathToClean: string): Promise<
|
|
317
|
+
cleanPath(pathToClean: string): Promise<boolean>;
|
|
312
318
|
}
|
|
313
319
|
|
|
314
320
|
interface IBackup {
|
|
@@ -346,7 +352,7 @@ interface IProjectConfigService {
|
|
|
346
352
|
* Get value for a given config key path
|
|
347
353
|
* @param key the property key path
|
|
348
354
|
*/
|
|
349
|
-
getValue(key: string): any;
|
|
355
|
+
getValue(key: string, defaultValue?: any): any;
|
|
350
356
|
/**
|
|
351
357
|
* Set value for a given config key path
|
|
352
358
|
* @param key the property key path
|
package/lib/package-manager.js
CHANGED
|
@@ -21,7 +21,7 @@ const decorators_2 = require("./common/decorators");
|
|
|
21
21
|
const constants_1 = require("./constants");
|
|
22
22
|
const yok_1 = require("./common/yok");
|
|
23
23
|
class PackageManager {
|
|
24
|
-
constructor($errors, $npm, $options, $yarn, $pnpm, $logger, $userSettingsService) {
|
|
24
|
+
constructor($errors, $npm, $options, $yarn, $pnpm, $logger, $userSettingsService, $projectConfigService) {
|
|
25
25
|
this.$errors = $errors;
|
|
26
26
|
this.$npm = $npm;
|
|
27
27
|
this.$options = $options;
|
|
@@ -29,6 +29,7 @@ class PackageManager {
|
|
|
29
29
|
this.$pnpm = $pnpm;
|
|
30
30
|
this.$logger = $logger;
|
|
31
31
|
this.$userSettingsService = $userSettingsService;
|
|
32
|
+
this.$projectConfigService = $projectConfigService;
|
|
32
33
|
}
|
|
33
34
|
init() {
|
|
34
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -103,6 +104,16 @@ class PackageManager {
|
|
|
103
104
|
catch (err) {
|
|
104
105
|
this.$errors.fail(`Unable to read package manager config from user settings ${err}`);
|
|
105
106
|
}
|
|
107
|
+
try {
|
|
108
|
+
const configPm = this.$projectConfigService.getValue("cli.packageManager");
|
|
109
|
+
if (configPm) {
|
|
110
|
+
this.$logger.trace(`Determined packageManager to use from user config is: ${configPm}`);
|
|
111
|
+
pm = configPm;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.$logger.trace("Tried to read cli.packageManager from project config and failed. Error is: ", err);
|
|
116
|
+
}
|
|
106
117
|
if (pm === constants_1.PackageManagers.yarn || this.$options.yarn) {
|
|
107
118
|
this._packageManagerName = constants_1.PackageManagers.yarn;
|
|
108
119
|
return this.$yarn;
|
|
@@ -22,19 +22,25 @@ class ProjectCleanupService {
|
|
|
22
22
|
}
|
|
23
23
|
clean(pathsToClean) {
|
|
24
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
let success = true;
|
|
25
26
|
for (const pathToClean of pathsToClean) {
|
|
26
|
-
yield this.cleanPath(pathToClean).catch((error) => {
|
|
27
|
+
const isCleaned = yield this.cleanPath(pathToClean).catch((error) => {
|
|
27
28
|
this.$logger.trace(`Encountered error while cleaning. Error is: ${error.message}.`, error);
|
|
29
|
+
return false;
|
|
28
30
|
});
|
|
31
|
+
success = success && isCleaned;
|
|
29
32
|
}
|
|
33
|
+
return success;
|
|
30
34
|
});
|
|
31
35
|
}
|
|
32
36
|
cleanPath(pathToClean) {
|
|
33
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
38
|
this.spinner.clear();
|
|
39
|
+
let success = true;
|
|
40
|
+
let fileType;
|
|
35
41
|
if (!pathToClean || pathToClean.trim().length === 0) {
|
|
36
42
|
this.$logger.trace("cleanPath called with no pathToClean.");
|
|
37
|
-
return;
|
|
43
|
+
return success;
|
|
38
44
|
}
|
|
39
45
|
const filePath = path.resolve(this.$projectHelper.projectDir, pathToClean);
|
|
40
46
|
const displayPath = `${path.relative(this.$projectHelper.projectDir, filePath)}`.yellow;
|
|
@@ -44,16 +50,25 @@ class ProjectCleanupService {
|
|
|
44
50
|
if (stat.isDirectory()) {
|
|
45
51
|
this.$logger.trace(`Path '${filePath}' is a directory, deleting.`);
|
|
46
52
|
this.$fs.deleteDirectorySafe(filePath);
|
|
47
|
-
|
|
53
|
+
fileType = "directory";
|
|
48
54
|
}
|
|
49
55
|
else {
|
|
50
56
|
this.$logger.trace(`Path '${filePath}' is a file, deleting.`);
|
|
51
57
|
this.$fs.deleteFile(filePath);
|
|
52
|
-
|
|
58
|
+
fileType = "file";
|
|
53
59
|
}
|
|
54
|
-
|
|
60
|
+
success = !this.$fs.exists(filePath);
|
|
61
|
+
if (success) {
|
|
62
|
+
this.spinner.succeed(`Cleaned ${fileType} ${displayPath}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const message = `Failed to Clean ${fileType}`.red;
|
|
66
|
+
this.spinner.fail(`${message} ${displayPath}`);
|
|
67
|
+
}
|
|
68
|
+
return success;
|
|
55
69
|
}
|
|
56
70
|
this.$logger.trace(`Path '${filePath}' not found, skipping.`);
|
|
71
|
+
return success;
|
|
57
72
|
});
|
|
58
73
|
}
|
|
59
74
|
}
|
|
@@ -92,7 +92,11 @@ export default {
|
|
|
92
92
|
.filter(Boolean)
|
|
93
93
|
.map((c) => {
|
|
94
94
|
if (this.$fs.isRelativePath(c)) {
|
|
95
|
-
|
|
95
|
+
const dir = projectDir || this.projectHelper.projectDir;
|
|
96
|
+
if (!dir) {
|
|
97
|
+
return c;
|
|
98
|
+
}
|
|
99
|
+
return path.join(dir, c);
|
|
96
100
|
}
|
|
97
101
|
return c;
|
|
98
102
|
});
|
package/package.json
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const filePatterns = [${ testFiles }];
|
|
2
1
|
module.exports = function (config) {
|
|
3
2
|
const options = {
|
|
4
3
|
|
|
@@ -11,8 +10,8 @@ module.exports = function (config) {
|
|
|
11
10
|
frameworks: [${ frameworks }],
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
// list of files / patterns to load in the browser
|
|
15
|
-
files:
|
|
13
|
+
// list of files / patterns to load in the browser. Leave empty for webpack projects
|
|
14
|
+
// files: [],
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
// list of files to exclude
|
|
@@ -31,6 +30,16 @@ module.exports = function (config) {
|
|
|
31
30
|
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
|
32
31
|
reporters: ['progress'],
|
|
33
32
|
|
|
33
|
+
// configure optional coverage, enable via --env.codeCoverage
|
|
34
|
+
coverageReporter: {
|
|
35
|
+
dir: require('path').join(__dirname, './coverage'),
|
|
36
|
+
subdir: '.',
|
|
37
|
+
reporters: [
|
|
38
|
+
{ type: 'html' },
|
|
39
|
+
{ type: 'text-summary' }
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
|
|
34
43
|
|
|
35
44
|
// web server port
|
|
36
45
|
port: 9876,
|
|
@@ -74,41 +83,9 @@ module.exports = function (config) {
|
|
|
74
83
|
singleRun: false
|
|
75
84
|
};
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
config.set(options);
|
|
81
|
-
}
|
|
82
|
-
module.exports.filePatterns = filePatterns;
|
|
83
|
-
// You can also use RegEx if you'd like:
|
|
84
|
-
// module.exports.filesRegex = /\.\/tests\/.*\.ts$/;
|
|
85
|
-
|
|
86
|
-
function setWebpackPreprocessor(config, options) {
|
|
87
|
-
if (config && config.bundle) {
|
|
88
|
-
if (!options.preprocessors) {
|
|
89
|
-
options.preprocessors = {};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
options.files.forEach(file => {
|
|
93
|
-
if (!options.preprocessors[file]) {
|
|
94
|
-
options.preprocessors[file] = [];
|
|
95
|
-
}
|
|
96
|
-
options.preprocessors[file].push('webpack');
|
|
97
|
-
});
|
|
86
|
+
if(config._NS && config._NS.env && config._NS.env.codeCoverage) {
|
|
87
|
+
options.reporters = (options.reporters || []).concat(['coverage']);
|
|
98
88
|
}
|
|
99
|
-
}
|
|
100
89
|
|
|
101
|
-
|
|
102
|
-
if (config && config.bundle) {
|
|
103
|
-
const env = {};
|
|
104
|
-
env[config.platform] = true;
|
|
105
|
-
env.sourceMap = config.debugBrk;
|
|
106
|
-
env.appPath = config.appPath;
|
|
107
|
-
env.karmaWebpack = true;
|
|
108
|
-
options.webpack = require('./webpack.config')(env);
|
|
109
|
-
delete options.webpack.entry;
|
|
110
|
-
delete options.webpack.output.libraryTarget;
|
|
111
|
-
const invalidPluginsForUnitTesting = ["GenerateBundleStarterPlugin", "GenerateNativeScriptEntryPointsPlugin"];
|
|
112
|
-
options.webpack.plugins = options.webpack.plugins.filter(p => !invalidPluginsForUnitTesting.includes(p.constructor.name));
|
|
113
|
-
}
|
|
90
|
+
config.set(options);
|
|
114
91
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { runTestApp } from "@nativescript/unit-test-runner";
|
|
2
|
+
// import other polyfills here
|
|
3
|
+
|
|
4
|
+
declare let require: any;
|
|
5
|
+
|
|
6
|
+
runTestApp({
|
|
7
|
+
runTests: () => {
|
|
8
|
+
const tests = require.context("./", true, /\.spec\.ts$/);
|
|
9
|
+
tests.keys().map(tests);
|
|
10
|
+
},
|
|
11
|
+
});
|