Skip to content

Commit c8694d8

Browse files
author
Fatme
authored
Merge pull request #3956 from NativeScript/famte/validate-bundle-version
fix: validate bundle version on `tns preview --bundle` and `tns run --hmr` commands
2 parents fa55552 + 1502957 commit c8694d8

File tree

6 files changed

+129
-8
lines changed

6 files changed

+129
-8
lines changed

lib/commands/preview.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export class PreviewCommand implements ICommand {
22
public allowedParameters: ICommandParameter[] = [];
3+
private static MIN_SUPPORTED_WEBPACK_VERSION = "0.17.0";
34

45
constructor(private $bundleValidatorHelper: IBundleValidatorHelper,
56
private $liveSyncService: ILiveSyncService,
@@ -30,7 +31,7 @@ export class PreviewCommand implements ICommand {
3031

3132
public async canExecute(args: string[]): Promise<boolean> {
3233
await this.$networkConnectivityValidator.validate();
33-
this.$bundleValidatorHelper.validate();
34+
this.$bundleValidatorHelper.validate(PreviewCommand.MIN_SUPPORTED_WEBPACK_VERSION);
3435
return true;
3536
}
3637
}

lib/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,8 @@ export class IosProjectConstants {
227227
public static XcodeProjExtName = ".xcodeproj";
228228
public static XcodeSchemeExtName = ".xcscheme";
229229
}
230+
231+
export class BundleValidatorMessages {
232+
public static MissingBundlePlugin = "Passing --bundle requires a bundling plugin. No bundling plugin found or the specified bundling plugin is invalid.";
233+
public static NotSupportedVersion = `The NativeScript CLI requires nativescript-dev-webpack %s or later to work properly.`;
234+
}

lib/declarations.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,11 @@ interface IDeployCommandHelper {
841841
interface IBundleValidatorHelper {
842842
/**
843843
* Validates bundling options.
844+
* In case when minSupportedVersion is provided, gets the current version of nativescript-dev-webpack from package.json and compares with the provided version.
845+
* @param {string} minSupportedVersion the minimum supported version of nativescript-dev-webpack
844846
* @return {void}
845847
*/
846-
validate(): void;
848+
validate(minSupportedVersion?: string): void;
847849
}
848850

849851
interface INativeScriptCloudExtensionService {

lib/helpers/bundle-validator-helper.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import * as semver from "semver";
2+
import * as util from "util";
3+
import { BundleValidatorMessages } from "../constants";
4+
15
export class BundleValidatorHelper implements IBundleValidatorHelper {
26
private bundlersMap: IStringDictionary = {
37
webpack: "nativescript-dev-webpack"
@@ -9,13 +13,21 @@ export class BundleValidatorHelper implements IBundleValidatorHelper {
913
this.$projectData.initializeProjectData();
1014
}
1115

12-
public validate(): void {
16+
public validate(minSupportedVersion?: string): void {
1317
if (this.$options.bundle) {
1418
const bundlePluginName = this.bundlersMap[this.$options.bundle];
15-
const hasBundlerPluginAsDependency = this.$projectData.dependencies && this.$projectData.dependencies[bundlePluginName];
16-
const hasBundlerPluginAsDevDependency = this.$projectData.devDependencies && this.$projectData.devDependencies[bundlePluginName];
17-
if (!bundlePluginName || (!hasBundlerPluginAsDependency && !hasBundlerPluginAsDevDependency)) {
18-
this.$errors.fail("Passing --bundle requires a bundling plugin. No bundling plugin found or the specified bundling plugin is invalid.");
19+
const bundlerVersionInDependencies = this.$projectData.dependencies && this.$projectData.dependencies[bundlePluginName];
20+
const bundlerVersionInDevDependencies = this.$projectData.devDependencies && this.$projectData.devDependencies[bundlePluginName];
21+
if (!bundlePluginName || (!bundlerVersionInDependencies && !bundlerVersionInDevDependencies)) {
22+
this.$errors.fail(BundleValidatorMessages.MissingBundlePlugin);
23+
}
24+
25+
if (minSupportedVersion) {
26+
const currentVersion = bundlerVersionInDependencies || bundlerVersionInDevDependencies;
27+
const isBundleSupported = semver.gte(semver.coerce(currentVersion), semver.coerce(minSupportedVersion));
28+
if (!isBundleSupported) {
29+
this.$errors.failWithoutHelp(util.format(BundleValidatorMessages.NotSupportedVersion, minSupportedVersion));
30+
}
1931
}
2032
}
2133
}

lib/helpers/livesync-command-helper.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
2+
private static MIN_SUPPORTED_WEBPACK_VERSION_WITH_HMR = "0.17.0";
23

34
constructor(private $platformService: IPlatformService,
45
private $projectData: IProjectData,
@@ -133,7 +134,8 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
133134
result[availablePlatform.toLowerCase()] = validateOutput;
134135
}
135136

136-
this.$bundleValidatorHelper.validate();
137+
const minSupportedWebpackVersion = this.$options.hmr ? LiveSyncCommandHelper.MIN_SUPPORTED_WEBPACK_VERSION_WITH_HMR : null;
138+
this.$bundleValidatorHelper.validate(minSupportedWebpackVersion);
137139

138140
return result;
139141
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { Yok } from "../../lib/common/yok";
2+
import { BundleValidatorHelper } from "../../lib/helpers/bundle-validator-helper";
3+
import { assert } from "chai";
4+
import { format } from "util";
5+
import { BundleValidatorMessages } from "../../lib/constants";
6+
7+
interface ITestCase {
8+
name: string;
9+
isDependency?: boolean;
10+
currentWebpackVersion?: string;
11+
minSupportedWebpackVersion?: string;
12+
expectedError?: string;
13+
}
14+
15+
let error: string = null;
16+
17+
function createTestInjector(options: { dependencies?: IStringDictionary, devDependencies?: IStringDictionary }) {
18+
const testInjector = new Yok();
19+
testInjector.register("projectData", {
20+
initializeProjectData: () => ({}),
21+
dependencies: options.dependencies,
22+
devDependencies: options.devDependencies
23+
});
24+
testInjector.register("errors", {
25+
fail: (err: string) => error = err,
26+
failWithoutHelp: (err: string) => error = err
27+
});
28+
testInjector.register("options", ({ bundle: "webpack" }));
29+
testInjector.register("bundleValidatorHelper", BundleValidatorHelper);
30+
31+
return testInjector;
32+
}
33+
34+
describe("BundleValidatorHelper", () => {
35+
beforeEach(() => error = null);
36+
37+
let testCases: ITestCase[] = [
38+
{
39+
name: "should throw an error when no webpack plugin is installed",
40+
expectedError: BundleValidatorMessages.MissingBundlePlugin
41+
}
42+
];
43+
44+
["dependencies", "devDependencies"]
45+
.forEach(key => {
46+
const isDependency = key === "dependencies";
47+
48+
testCases = testCases.concat([
49+
{
50+
name: `should not throw an error when webpack is added as ${key}`,
51+
isDependency,
52+
currentWebpackVersion: "0.12.0",
53+
expectedError: null
54+
},
55+
{
56+
name: `should not throw an error when webpack's version is greater than minSupportedVersion when webpack is installed as ${key}`,
57+
isDependency,
58+
currentWebpackVersion: "0.13.1",
59+
minSupportedWebpackVersion: "0.13.0",
60+
expectedError: null
61+
},
62+
{
63+
name: `should not throw an error when webpack's version is equal to minSupportedVersion when webpack is installed as ${key}`,
64+
isDependency,
65+
currentWebpackVersion: "0.10.0",
66+
minSupportedWebpackVersion: "0.10.0",
67+
expectedError: null
68+
},
69+
{
70+
name: `should throw an error when webpack's version is lower than minSupportedVersion when webpack is installed as ${key}`,
71+
isDependency,
72+
currentWebpackVersion: "0.17.0",
73+
minSupportedWebpackVersion: "0.18.0",
74+
expectedError: format(BundleValidatorMessages.NotSupportedVersion, "0.18.0")
75+
},
76+
{
77+
name: `should not throw an error when prerelease version of webpack is installed as ${key}`,
78+
isDependency,
79+
currentWebpackVersion: "0.17.0-2018-09-28-173604-01",
80+
minSupportedWebpackVersion: "0.17.0",
81+
expectedError: null
82+
}
83+
]);
84+
});
85+
86+
_.each(testCases, (testCase: any) => {
87+
const deps = {
88+
"nativescript-dev-webpack": testCase.currentWebpackVersion
89+
};
90+
91+
it(`${testCase.name}`, async () => {
92+
const injector = createTestInjector({ dependencies: testCase.isDependency ? deps : null, devDependencies: !testCase.isDependency ? deps : null });
93+
const bundleValidatorHelper = injector.resolve("bundleValidatorHelper");
94+
bundleValidatorHelper.validate(testCase.minSupportedWebpackVersion);
95+
96+
assert.deepEqual(error, testCase.expectedError);
97+
});
98+
});
99+
});

0 commit comments

Comments
 (0)