diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b48cb0b8..8785a071 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -116,6 +116,7 @@ The scope must be one of the following:
* ionic
* nativescript
* nest
+* helpers
#### Subject
diff --git a/src/app.electron/index.ts b/src/app.electron/index.ts
index 7b51a98e..6f892961 100644
--- a/src/app.electron/index.ts
+++ b/src/app.electron/index.ts
@@ -13,11 +13,13 @@ import {
noop
} from '@angular-devkit/schematics';
import { Schema as ApplicationOptions } from './schema';
-import { prerun, getPrefix, getNpmScope, stringUtils, addRootDeps, updateAngularProjects, updateNxProjects, formatFiles, getJsonFromFile, updatePackageScripts, addPostinstallers, applyAppNamingConvention, getGroupByName, getAppName } from '../utils';
+import { prerun, getPrefix, getNpmScope, stringUtils, addRootDeps, updateAngularProjects, updateNxProjects, formatFiles, getJsonFromFile, updatePackageScripts, addPostinstallers, applyAppNamingConvention, getGroupByName, getAppName, missingNameArgument } from '../utils';
export default function (options: ApplicationOptions) {
if (!options.name) {
- throw new SchematicsException(`Missing name argument. Provide a name for your Electron app. Example: ng g app.electron sample`);
+ throw new SchematicsException(
+ missingNameArgument('Provide a name for your Electron app.', 'ng g app.electron sample')
+ );
}
if (!options.target) {
throw new SchematicsException(`Missing target argument. Provide the name of the web app in your workspace to use inside the electron app. ie, web-myapp`);
diff --git a/src/app.ionic/index.ts b/src/app.ionic/index.ts
index a677af92..5eae902a 100644
--- a/src/app.ionic/index.ts
+++ b/src/app.ionic/index.ts
@@ -13,12 +13,14 @@ import {
schematic,
noop,
} from '@angular-devkit/schematics';
-import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, formatFiles, applyAppNamingConvention, getAppName } from '../utils';
+import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, formatFiles, applyAppNamingConvention, getAppName, missingNameArgument } from '../utils';
import { Schema as ApplicationOptions } from './schema';
export default function (options: ApplicationOptions) {
if (!options.name) {
- throw new SchematicsException(`Missing name argument. Provide a name for your Ionic app. Example: ng g app.ionic sample`);
+ throw new SchematicsException(
+ missingNameArgument('Provide a name for your Ionic app.', 'ng g app.ionic sample')
+ );
}
return chain([
diff --git a/src/app.nativescript/index.ts b/src/app.nativescript/index.ts
index 282ac2d4..dd32723f 100644
--- a/src/app.nativescript/index.ts
+++ b/src/app.nativescript/index.ts
@@ -13,12 +13,14 @@ import {
schematic,
noop,
} from '@angular-devkit/schematics';
-import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, applyAppNamingConvention, getGroupByName, getAppName } from '../utils';
+import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, applyAppNamingConvention, getGroupByName, getAppName, missingNameArgument } from '../utils';
import { Schema as ApplicationOptions } from './schema';
export default function (options: ApplicationOptions) {
if (!options.name) {
- throw new SchematicsException(`Missing name argument. Provide a name for your NativeScript app. Example: ng g app.nativescript sample`);
+ throw new SchematicsException(
+ missingNameArgument('Provide a name for your NativeScript app.', 'ng g app.nativescript sample')
+ );
}
return chain([
diff --git a/src/app.nest/index.ts b/src/app.nest/index.ts
index 2048e672..dd93eba3 100644
--- a/src/app.nest/index.ts
+++ b/src/app.nest/index.ts
@@ -26,13 +26,14 @@ import {
updateNxProjects,
prerun,
applyAppNamingConvention,
- getAppName
+ getAppName,
+ missingNameArgument
} from "../utils";
export default function(options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
- `Missing name argument. Provide a name for your Nest app. Example: ng g app.nest sample`
+ missingNameArgument('Provide a name for your Nest app.', 'ng g app.nest sample')
);
}
diff --git a/src/app.web/index.ts b/src/app.web/index.ts
index 3f23ff78..0b2ff8e3 100644
--- a/src/app.web/index.ts
+++ b/src/app.web/index.ts
@@ -23,7 +23,8 @@ import {
getJsonFromFile,
applyAppNamingConvention,
updateJsonFile,
- formatFiles
+ formatFiles,
+ missingNameArgument
} from "../utils";
import { Schema as ApplicationOptions } from "./schema";
@@ -31,7 +32,7 @@ let appName: string;
export default function(options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
- `Missing name argument. Provide a name for your web app. Example: ng g app my-app`
+ missingNameArgument('Provide a name for your Web app.', 'ng g app my-app')
);
}
appName = options.name;
@@ -169,27 +170,30 @@ platformBrowserDynamic()
function appCmpHtml() {
return `
`;
}
@@ -258,7 +262,7 @@ describe('AppComponent', () => {
})
);
it(
- 'should render title in a h1 tag',
+ 'should render xplat hello in a h2 tag',
async(() => {
spyOn(translate, 'getBrowserLang').and.returnValue('en');
translate.use('en');
@@ -274,7 +278,7 @@ describe('AppComponent', () => {
http.verify();
fixture.detectChanges();
- expect(compiled.querySelector('h1').textContent).toContain(
+ expect(compiled.querySelector('h2').textContent).toContain(
'Hello xplat'
);
})
diff --git a/src/utils/errors.ts b/src/utils/errors.ts
index d7179221..ab167f88 100644
--- a/src/utils/errors.ts
+++ b/src/utils/errors.ts
@@ -12,6 +12,18 @@ export function unsupportedHelperError(helper: string) {
return `${helper} is not a supported helper. Currently supported: ${supportedHelpers}`
}
+export function helperTargetError(helper: string) {
+ return `The xplat-helper "${helper}" requires the --target flag.`
+}
+
+export function helperMissingPlatforms() {
+ return `Missing platforms argument. Example: ng g xplat-helper imports --platforms=nativescript`;
+}
+
+export function missingNameArgument(description: string = '', example: string = '') {
+ return `Missing name argument. ${description} ${example ? 'Example: ' + example : ''}`;
+}
+
export function noPlatformError() {
return `You must specify which platforms you wish to generate support for. For example: ng g xplat --prefix=foo --platforms=${supportedPlatforms.join(',')}`
}
diff --git a/src/utils/general.ts b/src/utils/general.ts
index 0c96bded..fcc477bf 100644
--- a/src/utils/general.ts
+++ b/src/utils/general.ts
@@ -55,7 +55,7 @@ export interface NodeDependency {
// list of all supported helpers
// TODO: add more convenient helpers (like firebase or Travis ci support files)
-export const supportedHelpers = ['imports'];
+export const supportedHelpers = ['imports', 'applitools'];
let npmScope: string;
// selector prefix to use when generating various boilerplate for xplat support
@@ -92,6 +92,10 @@ export function setTest() {
isTest = true;
}
+export function isTesting() {
+ return isTest;
+}
+
export function serializeJson(json: any): string {
return `${JSON.stringify(json, null, 2)}\n`;
}
diff --git a/src/xplat-helper/applitools/index.ts b/src/xplat-helper/applitools/index.ts
new file mode 100644
index 00000000..e908da5a
--- /dev/null
+++ b/src/xplat-helper/applitools/index.ts
@@ -0,0 +1,11 @@
+import { Schema as HelperOptions } from "../schema";
+import { isTesting } from "../../utils";
+
+export * from './web/support';
+
+export function applitools_logNote(options: HelperOptions) {
+ if (!isTesting()) {
+ console.log(`Applitools support added for: ${options.target}`);
+ console.log(`Ensure your APPLITOOLS_API_KEY environment variable is set: https://applitools.com/tutorials/cypress.html#step-by-step-guide-run-the-demo-app`);
+ }
+}
\ No newline at end of file
diff --git a/src/xplat-helper/applitools/web/support.ts b/src/xplat-helper/applitools/web/support.ts
new file mode 100644
index 00000000..39c2330b
--- /dev/null
+++ b/src/xplat-helper/applitools/web/support.ts
@@ -0,0 +1,126 @@
+import {
+ Tree, SchematicContext, noop,
+} from "@angular-devkit/schematics";
+import {
+ updateTsConfig, createOrUpdate, updatePackageScripts, getJsonFromFile, updateJsonFile
+} from "../../../utils";
+import { Schema as HelperOptions } from "../../schema";
+
+export function supportApplitools_Web(
+ helperChains: Array,
+ options: HelperOptions
+) {
+ return (tree: Tree, context: SchematicContext) => {
+ // update support index
+ helperChains.push(
+ createOrUpdate(
+ tree,
+ `/apps/${options.target}-e2e/src/support/index.ts`,
+ updateCypressIndex()
+ )
+ );
+ // update plugin index
+ helperChains.push(
+ createOrUpdate(
+ tree,
+ `/apps/${options.target}-e2e/src/plugins/index.ts`,
+ updateCypressPlugins()
+ )
+ );
+ // ensure supportFile points to updates
+ const cypressConfigPath = `/apps/${options.target}-e2e/cypress.json`;
+ const cypressConfig = getJsonFromFile(tree, cypressConfigPath);
+ // console.log('cypressConfig:', cypressConfig);
+ // plugin path is always defined so ensure support matches
+ const pluginsFilePath = cypressConfig.pluginsFile;
+ // console.log('pluginsFilePath:', pluginsFilePath);
+ const outputPath = pluginsFilePath.split('plugins/')[0];
+ cypressConfig.supportFile = `${outputPath}support/index.js`;
+ // console.log('cypressConfig.supportFile:', cypressConfig.supportFile);
+ helperChains.push(updateJsonFile(tree, cypressConfigPath, cypressConfig));
+ // update sample test
+ helperChains.push(
+ createOrUpdate(
+ tree,
+ `/apps/${options.target}-e2e/src/integration/app.spec.ts`,
+ updateSampleTest()
+ )
+ );
+ };
+}
+
+function updateCypressIndex() {
+ return `// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Applitools support
+import '@applitools/eyes-cypress/commands';
+
+// Import commands.js using ES2015 syntax:
+import './commands';
+`;
+}
+
+function updateCypressPlugins() {
+ return `// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+module.exports = (on: any, config: any) => {
+ // 'on' is used to hook into various events Cypress emits
+ // 'config' is the resolved Cypress config
+};
+
+// Applitools
+require('@applitools/eyes-cypress')(module);
+`;
+}
+
+function updateSampleTest() {
+ return `import { getGreeting } from '../support/app.po';
+
+describe('Hello Nx', () => {
+ beforeEach(() => cy.visit('/'));
+
+ it('should display welcome message', () => {
+
+ // start applitools test
+ (cy).eyesOpen({
+ appName: 'myapp',
+ testName: 'Welcome message',
+ browser: { width: 800, height: 600 },
+ });
+
+ // check window with applitools
+ (cy).eyesCheckWindow('Main Page');
+
+ // standard cypress testing
+ getGreeting().contains('Welcome to web-myapp!');
+
+ // end applitools test
+ (cy).eyesClose();
+ });
+});
+`;
+}
\ No newline at end of file
diff --git a/src/xplat-helper/imports/index.ts b/src/xplat-helper/imports/index.ts
new file mode 100644
index 00000000..cb1c3921
--- /dev/null
+++ b/src/xplat-helper/imports/index.ts
@@ -0,0 +1 @@
+export * from './nativescript/support';
\ No newline at end of file
diff --git a/src/xplat-helper/nativescript/imports/_files/@nativescript/angular/core.ts b/src/xplat-helper/imports/nativescript/_files/@nativescript/angular/core.ts
similarity index 100%
rename from src/xplat-helper/nativescript/imports/_files/@nativescript/angular/core.ts
rename to src/xplat-helper/imports/nativescript/_files/@nativescript/angular/core.ts
diff --git a/src/xplat-helper/nativescript/imports/_files/@nativescript/angular/index.ts b/src/xplat-helper/imports/nativescript/_files/@nativescript/angular/index.ts
similarity index 100%
rename from src/xplat-helper/nativescript/imports/_files/@nativescript/angular/index.ts
rename to src/xplat-helper/imports/nativescript/_files/@nativescript/angular/index.ts
diff --git a/src/xplat-helper/nativescript/imports/_files/@nativescript/core.ts b/src/xplat-helper/imports/nativescript/_files/@nativescript/core.ts
similarity index 100%
rename from src/xplat-helper/nativescript/imports/_files/@nativescript/core.ts
rename to src/xplat-helper/imports/nativescript/_files/@nativescript/core.ts
diff --git a/src/xplat-helper/nativescript/imports/_files/@nativescript/ui.ts b/src/xplat-helper/imports/nativescript/_files/@nativescript/ui.ts
similarity index 100%
rename from src/xplat-helper/nativescript/imports/_files/@nativescript/ui.ts
rename to src/xplat-helper/imports/nativescript/_files/@nativescript/ui.ts
diff --git a/src/xplat-helper/imports/nativescript/support.ts b/src/xplat-helper/imports/nativescript/support.ts
new file mode 100644
index 00000000..ab8ad1fd
--- /dev/null
+++ b/src/xplat-helper/imports/nativescript/support.ts
@@ -0,0 +1,70 @@
+import {
+ Tree, SchematicContext,
+} from "@angular-devkit/schematics";
+import {
+ updateTsConfig
+} from "../../../utils";
+import { Schema as HelperOptions } from "../../schema";
+
+export function supportImports_NativeScript(
+ helperChains: Array,
+ options: HelperOptions
+) {
+ return (tree: Tree, context: SchematicContext) => {
+ let pathRef = `xplat/nativescript/utils/@nativescript/*`;
+ // update root tsconfig
+ helperChains.push(
+ updateTsConfig(tree, (tsConfig: any) => {
+ const updates: any = {};
+ updates[`@nativescript/*`] = [pathRef];
+ if (tsConfig) {
+ if (!tsConfig.compilerOptions) {
+ tsConfig.compilerOptions = {};
+ }
+ tsConfig.compilerOptions.paths = {
+ ...(tsConfig.compilerOptions.paths || {}),
+ ...updates
+ };
+ }
+ })
+ );
+
+ // update all {N} app tsconfig's
+ const appsDir = tree.getDir("apps");
+ const appFolders = appsDir.subdirs;
+ pathRef = `../../${pathRef}`;
+
+ // update {N} apps and configs
+ for (const dir of appFolders) {
+ // console.log(dir);
+ if (
+ dir.indexOf("nativescript-") === 0 ||
+ dir.indexOf("-nativescript") === 0
+ ) {
+ const appDir = `${appsDir.path}/${dir}`;
+ // console.log('appDir:', appDir);
+
+ helperChains.push(
+ updateTsConfig(
+ tree,
+ (tsConfig: any) => {
+ const updates: any = {};
+ updates[`@nativescript/*`] = [pathRef];
+ if (tsConfig) {
+ if (!tsConfig.compilerOptions) {
+ tsConfig.compilerOptions = {};
+ }
+ tsConfig.compilerOptions.paths = {
+ ...(tsConfig.compilerOptions.paths || {}),
+ ...updates
+ };
+ }
+ },
+ null,
+ `${appDir}/`
+ )
+ );
+ }
+ }
+ };
+}
diff --git a/src/xplat-helper/index.ts b/src/xplat-helper/index.ts
index 541b9ffc..4bae50ac 100644
--- a/src/xplat-helper/index.ts
+++ b/src/xplat-helper/index.ts
@@ -29,67 +29,158 @@ import {
PlatformTypes,
supportedPlatforms,
unsupportedPlatformError,
+ helperMissingPlatforms,
supportedHelpers,
unsupportedHelperError,
- updateTsConfig
+ updateTsConfig,
+ helperTargetError,
+ missingNameArgument
} from "../utils";
import { Schema as HelperOptions } from "./schema";
+// Helpers
+import { supportApplitools_Web, applitools_logNote } from "./applitools";
+import { supportImports_NativeScript } from "./imports";
+// Configuration options for each helper
+interface ISupportConfig {
+ platforms: Array;
+ requiresTarget?: boolean;
+ moveTo?: (platform: PlatformTypes, target?: string) => string;
+ additionalSupport?: (
+ platform: PlatformTypes,
+ helperChains: Array,
+ options: HelperOptions
+ ) => (tree: Tree, context: SchematicContext) => void;
+}
+interface IHelperSupportConfig {
+ imports: ISupportConfig;
+ applitools: ISupportConfig;
+}
+// Mapping config of what each helper supports
+const helperSupportConfig: IHelperSupportConfig = {
+ imports: {
+ platforms: ["nativescript"],
+ moveTo: function(platform: PlatformTypes, target?: string) {
+ return `xplat/${platform}/utils`;
+ },
+ additionalSupport: function(
+ platform: PlatformTypes,
+ helperChains: Array,
+ options: HelperOptions
+ ) {
+ switch (platform) {
+ case "nativescript":
+ return supportImports_NativeScript(helperChains, options);
+ }
+ }
+ },
+ applitools: {
+ platforms: ["web"],
+ requiresTarget: true,
+ additionalSupport: function(
+ platform: PlatformTypes,
+ helperChains: Array,
+ options: HelperOptions
+ ) {
+ switch (platform) {
+ case "web":
+ return supportApplitools_Web(helperChains, options);
+ }
+ }
+ }
+};
let helpers: Array = [];
-let platforms: Array = [];
+let platforms: Array = [];
export default function(options: HelperOptions) {
if (!options.name) {
throw new SchematicsException(
- `Missing name argument. Provide a comma delimited list of helpers to generate. Example: ng g xplat-helper imports`
- );
- }
- if (!options.platforms) {
- throw new SchematicsException(
- `Missing platforms argument. Example: ng g xplat-helper imports --platforms=nativescript`
+ missingNameArgument('Provide a comma delimited list of helpers to generate.', 'ng g xplat-helper imports')
);
}
-
helpers = options.name.split(",");
- platforms = options.platforms.split(",");
+ platforms = >(
+ (options.platforms ? options.platforms.split(",") : [])
+ );
const helperChains = [];
- for (const platform of platforms) {
- if (supportedPlatforms.includes(platform)) {
- for (const helper of helpers) {
- if (supportedHelpers.includes(helper)) {
- const moveTo = getMoveTo(platform, helper);
- helperChains.push((tree: Tree, context: SchematicContext) => {
- return addHelperFiles(
- options,
- platform,
- helper,
- moveTo
- )(tree, context);
- });
- // aside from adding files above, process any additional modifications
- helperChains.push((tree: Tree, context: SchematicContext) => {
- return processSupportingFiles(
- helperChains,
- options,
- platform,
- helper
- );
- });
- } else {
- throw new SchematicsException(unsupportedHelperError(helper));
+ const processHelpers = (platform?: PlatformTypes) => {
+ for (const helper of helpers) {
+ if (supportedHelpers.includes(helper)) {
+ // get helper support config
+ const supportConfig: ISupportConfig = helperSupportConfig[helper];
+ if (!platform) {
+ // when using targeting the platforms argument can be ommitted
+ // however when doing so it relies on platform being in the target name
+ if (supportConfig.requiresTarget && options.target) {
+ for (const p of supportedPlatforms) {
+ const match = options.target.match(p);
+ if (match) {
+ platform = match[0];
+ break;
+ }
+ }
+ }
+ }
+ // if platform is still falsey, error out
+ if (!platform) {
+ throw new SchematicsException(helperMissingPlatforms());
+ }
+ // throw is target required and it's missing
+ if (supportConfig.requiresTarget && !options.target) {
+ throw new SchematicsException(helperTargetError(helper));
+ }
+
+ if (supportConfig.platforms.includes(platform)) {
+ if (supportConfig.moveTo) {
+ // add files for the helper
+ const moveTo = supportConfig.moveTo(platform, options.target);
+ helperChains.push((tree: Tree, context: SchematicContext) => {
+ return addHelperFiles(options, platform, helper, moveTo)(
+ tree,
+ context
+ );
+ });
+ }
+
+ if (supportConfig.additionalSupport) {
+ // process additional support modifications
+ helperChains.push((tree: Tree, context: SchematicContext) => {
+ return supportConfig.additionalSupport(
+ platform,
+ helperChains,
+ options
+ )(tree, context);
+ });
+ }
}
+ } else {
+ throw new SchematicsException(unsupportedHelperError(helper));
}
- } else {
- throw new SchematicsException(unsupportedPlatformError(platform));
}
+ };
+
+ if (platforms.length) {
+ for (const platform of platforms) {
+ if (supportedPlatforms.includes(platform)) {
+ processHelpers(platform);
+ } else {
+ throw new SchematicsException(unsupportedPlatformError(platform));
+ }
+ }
+ } else {
+ processHelpers();
}
return chain([
prerun(options),
// add helper chains
- ...helperChains
- // TODO: add refactor code to update per the helper where applicable
+ ...helperChains,
+ // log additional notes
+ (tree: Tree) => {
+ logNotes(options, helpers);
+ return noop();
+ }
]);
}
@@ -101,7 +192,7 @@ function addHelperFiles(
): Rule {
return branchAndMerge(
mergeWith(
- apply(url(`./${platform}/${helper}/_files`), [
+ apply(url(`./${helper}/${platform}/_files`), [
template({
...(options as any),
utils: stringUtils,
@@ -115,77 +206,12 @@ function addHelperFiles(
);
}
-function getMoveTo(platform: PlatformTypes, helper: string) {
- let moveTo = `xplat/${platform}/utils`; // default
- // TODO: define custom moveTo locations for various helpers
- // switch (helper) {
- // case "imports":
- // break;
- // }
- return moveTo;
-}
-
-function processSupportingFiles(
- helperChains: Array,
- options: HelperOptions,
- platform: PlatformTypes,
- helper: string
-) {
- return (tree: Tree) => {
+function logNotes(options: HelperOptions, helpers: string[]) {
+ for (const helper of helpers) {
switch (helper) {
- case "imports":
- switch (platform) {
- case "nativescript":
- let pathRef = `xplat/nativescript/utils/@nativescript/*`;
- // update root tsconfig
- helperChains.push(updateTsConfig(tree, (tsConfig: any) => {
- const updates: any = {};
- updates[`@nativescript/*`] = [
- pathRef
- ];
- if (tsConfig) {
- if (!tsConfig.compilerOptions) {
- tsConfig.compilerOptions = {};
- }
- tsConfig.compilerOptions.paths = {
- ...(tsConfig.compilerOptions.paths || {}),
- ...updates
- };
- }
- }));
-
- // update all {N} app tsconfig's
- const appsDir = tree.getDir("apps");
- const appFolders = appsDir.subdirs;
- pathRef = `../../${pathRef}`;
-
- // update {N} apps and configs
- for (const dir of appFolders) {
- // console.log(dir);
- if (dir.indexOf('nativescript-') === 0 || dir.indexOf('-nativescript') === 0) {
- const appDir = `${appsDir.path}/${dir}`;
- // console.log('appDir:', appDir);
-
- helperChains.push(updateTsConfig(tree, (tsConfig: any) => {
- const updates: any = {};
- updates[`@nativescript/*`] = [
- pathRef
- ];
- if (tsConfig) {
- if (!tsConfig.compilerOptions) {
- tsConfig.compilerOptions = {};
- }
- tsConfig.compilerOptions.paths = {
- ...(tsConfig.compilerOptions.paths || {}),
- ...updates
- };
- }
- }, null, `${appDir}/`));
- }
- }
- break;
- }
+ case "applitools":
+ applitools_logNote(options);
break;
}
- };
+ }
}
diff --git a/src/xplat-helper/index_spec.ts b/src/xplat-helper/index_spec.ts
index 375afd4b..f6c79b0b 100644
--- a/src/xplat-helper/index_spec.ts
+++ b/src/xplat-helper/index_spec.ts
@@ -1,22 +1,20 @@
import { Tree, VirtualTree } from '@angular-devkit/schematics';
-import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
+import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { getFileContent } from '@schematics/angular/utility/test';
import * as path from 'path';
-import { Schema as AppOptions } from '../app.nativescript/schema';
+import { Schema as AppWebOptions } from '../app.web/schema';
+import { Schema as AppNativeScriptOptions } from '../app.nativescript/schema';
import { Schema as XPlatOptions } from '../xplat/schema';
import { Schema as HelperOptions } from './schema';
-import { stringUtils, isInModuleMetadata, createEmptyWorkspace } from '../utils';
+import { stringUtils, isInModuleMetadata, createEmptyWorkspace, setTest } from '../utils';
+setTest();
describe('xplat-helper schematic', () => {
const schematicRunner = new SchematicTestRunner(
'@nstudio/schematics',
path.join(__dirname, '../collection.json'),
);
- const defaultOptions: HelperOptions = {
- name: 'imports',
- platforms: 'nativescript'
- };
let appTree: Tree;
@@ -25,7 +23,7 @@ describe('xplat-helper schematic', () => {
appTree = createEmptyWorkspace(appTree);
});
- it('should create all files for the helper', () => {
+ it('imports: should create all files', () => {
const optionsXplat: XPlatOptions = {
npmScope: 'testing',
prefix: 'tt',
@@ -33,7 +31,7 @@ describe('xplat-helper schematic', () => {
};
appTree = schematicRunner.runSchematic('xplat', optionsXplat, appTree);
- const appOptions: AppOptions = {
+ const appOptions: AppNativeScriptOptions = {
name: 'foo',
npmScope: 'testing',
sample: true,
@@ -42,7 +40,10 @@ describe('xplat-helper schematic', () => {
// console.log('appTree:', appTree);
appTree = schematicRunner.runSchematic('app.nativescript', appOptions, appTree);
- const options: HelperOptions = { ...defaultOptions };
+ const options: HelperOptions = {
+ name: 'imports',
+ platforms: 'nativescript'
+ };
// console.log('appTree:', appTree);
const tree = schematicRunner.runSchematic('xplat-helper', options, appTree);
const files = tree.files;
@@ -65,6 +66,98 @@ describe('xplat-helper schematic', () => {
expect(fileContent.compilerOptions.paths['@nativescript/*'][0]).toBe('../../xplat/nativescript/utils/@nativescript/*');
});
+ it('applitools: should create all files', async () => {
+ const optionsXplat: XPlatOptions = {
+ npmScope: 'testing',
+ prefix: 'tt',
+ platforms: 'web,nativescript'
+ };
+
+ appTree = schematicRunner.runSchematic('xplat', optionsXplat, appTree);
+ const appOptions: AppWebOptions = {
+ name: 'foo',
+ prefix: 'tt',
+ e2eTestRunner: 'cypress'
+ };
+ // console.log('appTree:', appTree);
+ appTree = await schematicRunner.runSchematicAsync('app', appOptions, appTree).toPromise();
+
+ const cypressJsonPath = '/apps/web-foo-e2e/cypress.json';
+ let fileContent = getFileContent(appTree, cypressJsonPath);
+ let cypressJson = JSON.parse(fileContent);
+ expect(cypressJson.supportFile).toBe(false);
+
+ const options: HelperOptions = {
+ name: 'applitools',
+ target: 'web-foo'
+ };
+ // console.log('appTree:', appTree);
+ const tree = schematicRunner.runSchematic('xplat-helper', options, appTree);
+ const files = tree.files;
+ // console.log(files);
+
+ expect(files.indexOf('/apps/web-foo-e2e/src/support/index.ts')).toBeGreaterThanOrEqual(0);
+ expect(files.indexOf('/apps/web-foo-e2e/src/plugins/index.ts')).toBeGreaterThanOrEqual(0);
+ // modified testing files
+ let filePath = '/apps/web-foo-e2e/src/support/index.ts';
+ fileContent = getFileContent(tree, filePath)
+ // console.log(fileContent);
+
+ expect(fileContent.indexOf('@applitools/eyes-cypress/commands')).toBeGreaterThanOrEqual(0);
+
+ filePath = '/apps/web-foo-e2e/src/plugins/index.ts';
+ fileContent = getFileContent(tree, filePath)
+ // console.log(fileContent);
+
+ expect(fileContent.indexOf(`require('@applitools/eyes-cypress')(module);`)).toBeGreaterThanOrEqual(0);
+
+ fileContent = getFileContent(tree, cypressJsonPath);
+ // console.log(fileContent);
+ cypressJson = JSON.parse(fileContent);
+ expect(cypressJson.supportFile).toBe(`../../dist/out-tsc/apps/web-foo-e2e/src/support/index.js`);
+
+ filePath = '/apps/web-foo-e2e/src/integration/app.spec.ts';
+ fileContent = getFileContent(tree, filePath)
+ // console.log(fileContent);
+
+ expect(fileContent.indexOf(`eyesOpen`)).toBeGreaterThanOrEqual(0);
+ });
+
+ it('applitools: should throw if target is missing', async () => {
+ const optionsXplat: XPlatOptions = {
+ npmScope: 'testing',
+ prefix: 'tt',
+ platforms: 'web,nativescript'
+ };
+
+ appTree = schematicRunner.runSchematic('xplat', optionsXplat, appTree);
+ const appOptions: AppWebOptions = {
+ name: 'foo',
+ prefix: 'tt',
+ e2eTestRunner: 'cypress'
+ };
+ // console.log('appTree:', appTree);
+ appTree = await schematicRunner.runSchematicAsync('app', appOptions, appTree).toPromise();
+
+ const cypressJsonPath = '/apps/web-foo-e2e/cypress.json';
+ let fileContent = getFileContent(appTree, cypressJsonPath);
+ let cypressJson = JSON.parse(fileContent);
+ expect(cypressJson.supportFile).toBe(false);
+
+ const options: HelperOptions = {
+ name: 'applitools',
+ platforms: 'web'
+ };
+ // console.log('appTree:', appTree);
+ let tree;
+
+ expect(
+ () => (tree = schematicRunner.runSchematic('xplat-helper', options, appTree))
+ ).toThrowError(
+ `The xplat-helper "applitools" requires the --target flag.`
+ );
+ });
+
it('generating helper for a platform where the helper is not supported should not do anything', () => {
const optionsXplat: XPlatOptions = {
npmScope: 'testing',
diff --git a/src/xplat-helper/schema.d.ts b/src/xplat-helper/schema.d.ts
index 7bbd69b7..60b57eb4 100644
--- a/src/xplat-helper/schema.d.ts
+++ b/src/xplat-helper/schema.d.ts
@@ -7,8 +7,18 @@ export interface Schema {
* Target platforms to generate helpers for.
*/
platforms?: string;
+ /**
+ * Optional target when adding helpers
+ */
+ target?: string;
/**
* Skip refactoring code to support the helper where supported.
+ * TODO
+ * "skipRefactor": {
+ "type": "boolean",
+ "description": "Skip refactoring code to support the helper where supported.",
+ "default": false
+ }
*/
- skipRefactor?: boolean;
+ // skipRefactor?: boolean;
}
diff --git a/src/xplat-helper/schema.json b/src/xplat-helper/schema.json
index 79eaa8e4..7398b7c5 100644
--- a/src/xplat-helper/schema.json
+++ b/src/xplat-helper/schema.json
@@ -17,10 +17,9 @@
"type": "string",
"description": "Target platforms to generate helpers for."
},
- "skipRefactor": {
- "type": "boolean",
- "description": "Skip refactoring code to support the helper where supported.",
- "default": false
+ "target": {
+ "type": "string",
+ "description": "Some helpers support targeting to generate the helper for a specific target. ie: ng g xplat-helper applitools --target=web-myapp"
}
},
"required": []