Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/lib/commands/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const doc: DocCommandType = {
},
open: async (target) => {
const open = await import("open");
open.default.call(target);
await open.default(target);
},
async handler(argv: ArgumentsCamelCase<PositionalArgs>) {
GoogleAnalytics.post({
Expand Down
2 changes: 1 addition & 1 deletion packages/core/util/ProjectConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class ProjectConfig {

const result = { message: undefined, valid: false, value: undefined };
if (!schema.properties.hasOwnProperty(property)) {
result.message = `Property "${property}" is not allowed in "${schema.title}" type!`;
result.message = `Property "${property}" is not allowed in the Ignite UI CLI configuration!`;
return result;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/igx-templates/igx-ts/grid/grid-custom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ class IgxCustomGridTemplate extends IgniteUIForAngularTemplate {
const featuresUrls = [];
for (const feature of this.userExtraConfiguration["columnFeatures"] as string[]) {
switch (feature) {
case "Sorting":
case "Filtering":
gridFeatures.push(`[allowFiltering]="true"`);
// falls through
case "Sorting":
case "Resizing":
const text = `[${feature.toLowerCase().replace("ing", "able")}]="true"`;
columnFeatures.push(text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class IgxMultiColumnHeadersTemplate extends IgniteUIForAngularTemplate {

public getExtraConfiguration(): ControlExtraConfiguration[] {
return [{
choices: ["Sorting", "Filtering", "Resizing", "Paging", "Column Pinning", "Moving"],
choices: ["Sorting", "Filtering", "Resizing", "Paging", "Moving"],
default: "",
key: "columnFeatures",
message: "Choose features for the igx-grid",
Expand All @@ -49,11 +49,13 @@ class IgxMultiColumnHeadersTemplate extends IgniteUIForAngularTemplate {
case "Sorting":
case "Filtering":
case "Resizing":
case "Moving":
const text = `[${feature.toLowerCase().replace("ing", "able")}]="true"`;
columnFeatures.push(text);
columnBoolFeatures.push(text);
break;
case "Moving":
gridFeatures.push(`[moving]="true"`);
break;
case "Row Selection":
const gridFeatureText = `rowSelection="multiple"`;
gridFeatures.push(gridFeatureText);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { ControlExtraConfigType, ControlExtraConfiguration } from "@igniteui/cli-core";
import { ControlExtraConfigType, ControlExtraConfiguration, TemplateDependency } from "@igniteui/cli-core";
import { IgniteUIForAngularTemplate } from "../../../IgniteUIForAngularTemplate";
import { IGNITEUI_ANGULAR_PACKAGE } from "../../../constants";

const BASE_DEPENDENCIES: TemplateDependency[] = [
{
import: [
"IgxHierarchicalGridComponent",
"IgxRowIslandComponent",
"IgxColumnComponent",
"IgxIconComponent"
],
from: "<%=igxPackage%>",
standalone: true
}
];

class IgxHierarchicalGridTemplate extends IgniteUIForAngularTemplate {
private userExtraConfiguration = {};
private usePinning: boolean;
Expand All @@ -16,18 +29,7 @@ class IgxHierarchicalGridTemplate extends IgniteUIForAngularTemplate {
this.projectType = "igx-ts";
this.name = "Custom Hierarchical Grid";
this.description = "a customizable IgxHierarchicalGrid";
this.dependencies = [
{
import: [
"IgxHierarchicalGridComponent",
"IgxRowIslandComponent",
"IgxColumnComponent",
"IgxIconComponent"
],
from: "<%=igxPackage%>",
standalone: true
}
];
this.dependencies = [...BASE_DEPENDENCIES];
this.packages = [IGNITEUI_ANGULAR_PACKAGE];
this.hasExtraConfiguration = true;
}
Expand All @@ -48,6 +50,10 @@ class IgxHierarchicalGridTemplate extends IgniteUIForAngularTemplate {
}

public generateConfig(name: string, ...options: any[]): {[key: string]: any} {
// the template instance is shared, so reset state left over from previous calls
this.usePinning = false;
this.additionalElements = [""];
this.dependencies = [...BASE_DEPENDENCIES];
const columnFeatures = [];
const gridFeatures = [];
const extraConfig = {
Expand Down Expand Up @@ -139,57 +145,57 @@ class IgxHierarchicalGridTemplate extends IgniteUIForAngularTemplate {
}

featuresUrls.push(this.getFeatureUrl(feature, featureUrl));
selectedFeatures = features.map((e, i) => {
anchorWrapper.href = featuresUrls[i];
anchorWrapper.text = e;
return ` ${anchorWrapper.start}${anchorWrapper.href}${anchorWrapper.middle}` +
`${anchorWrapper.text}${anchorWrapper.end}`;
}).toString();
if (selectedFeatures.length > 0) {
selectedFeatures = `<p>Active Features: ${selectedFeatures}</p>`;
}
if (toolbarActions.length) {
this.dependencies = [
...this.dependencies,
...[
{
standalone: true,
import: "IgxGridToolbarComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarTitleComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarActionsComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarPinningComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarHidingComponent",
from: "<%=igxPackage%>"
},
],
];
}
selectedFeatures = features.map((e, i) => {
anchorWrapper.href = featuresUrls[i];
anchorWrapper.text = e;
return ` ${anchorWrapper.start}${anchorWrapper.href}${anchorWrapper.middle}` +
`${anchorWrapper.text}${anchorWrapper.end}`;
}).toString();
if (selectedFeatures.length > 0) {
selectedFeatures = `<p>Active Features: ${selectedFeatures}</p>`;
}
if (toolbarActions.length) {
this.dependencies = [
...this.dependencies,
...[
{
standalone: true,
import: "IgxGridToolbarComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarTitleComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarActionsComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarPinningComponent",
from: "<%=igxPackage%>"
},
{
standalone: true,
import: "IgxGridToolbarHidingComponent",
from: "<%=igxPackage%>"
},
],
];

const parts = [
" <igx-grid-toolbar>",
" <igx-grid-toolbar-title>Singers</igx-grid-toolbar-title>",
" <igx-grid-toolbar-actions>",
...toolbarActions,
" </igx-grid-toolbar-actions>",
" </igx-grid-toolbar>"
];
this.additionalElements.splice(1, 0, parts.join("\n"));
}
const parts = [
" <igx-grid-toolbar>",
" <igx-grid-toolbar-title>Singers</igx-grid-toolbar-title>",
" <igx-grid-toolbar-actions>",
...toolbarActions,
" </igx-grid-toolbar-actions>",
" </igx-grid-toolbar>"
];
this.additionalElements.splice(1, 0, parts.join("\n"));
}
}

Expand Down
32 changes: 32 additions & 0 deletions packages/ng-schematics/src/utils/cli-config.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { EmptyTree, SchematicContext, SchematicsException } from "@angular-devkit/schematics";
import { UnitTestTree } from "@angular-devkit/schematics/testing";
import { createCliConfig } from "./cli-config";

describe("createCliConfig", () => {
let tree: UnitTestTree;
let context: SchematicContext;

beforeEach(() => {
tree = new UnitTestTree(new EmptyTree());
context = {
logger: jasmine.createSpyObj("logger", ["info", "warn"])
} as unknown as SchematicContext;
});

it("should report a missing angular.json", async () => {
const rule = createCliConfig() as (tree: UnitTestTree, context: SchematicContext) => Promise<void>;

await expectAsync(rule(tree, context))
.toBeRejectedWithError(SchematicsException, "angular.json was not found in the project's root");
expect(tree.exists("ignite-ui-cli.json")).toBeFalse();
});

it("should report a missing angular.json when the root has other files", async () => {
tree.create("package.json", "{}");
const rule = createCliConfig() as (tree: UnitTestTree, context: SchematicContext) => Promise<void>;

await expectAsync(rule(tree, context))
.toBeRejectedWithError(SchematicsException, "angular.json was not found in the project's root");
expect(tree.exists("ignite-ui-cli.json")).toBeFalse();
});
});
4 changes: 3 additions & 1 deletion packages/ng-schematics/src/utils/cli-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ async function GetCliConfig(tree: Tree): Promise<Config> {
try {
({ workspace } = await workspaces.readWorkspace("/", createWorkspaceHost(tree)));
} catch (e) {
if (e.toString().includes("Could not find (undefined)")) {
const message = e.toString();
if (message.includes("Unable to determine format for workspace path") ||
message.includes("Unable to locate a workspace file")) {
throw new SchematicsException("angular.json was not found in the project's root");
}
throw new Error(e.message);
Expand Down
11 changes: 11 additions & 0 deletions spec/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,14 @@ export function filesDiff(
export function resetSpy(spy: any) {
(spy as jasmine.Spy).calls.reset();
}

/**
* Loads a fresh copy of a module, bypassing the require cache.
* Use for modules that export a stateful singleton, like template instances.
* @param modulePath Absolute path to the module
*/
export function requireFresh<T>(modulePath: string): T {
const resolved = require.resolve(modulePath);
delete require.cache[resolved];
return require(resolved);
}
8 changes: 8 additions & 0 deletions spec/unit/ProjectConfig-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,12 @@ describe("Unit - ProjectConfig", () => {
expect(ProjectConfig.hasLocalConfig()).toBeTruthy();
expect(fs.statSync).toHaveBeenCalledTimes(1);
});

it("validateProperty rejects properties that are not in the schema", () => {
const result = ProjectConfig.validateProperty("notAConfigProperty", "value");
expect(result.valid).toBeFalse();
expect(result.value).toBeUndefined();
expect(result.message)
.toBe(`Property "notAConfigProperty" is not allowed in the Ignite UI CLI configuration!`);
});
});
14 changes: 14 additions & 0 deletions spec/unit/doc-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@ describe("Unit - Doc command", () => {
expect(Util.error).toHaveBeenCalledWith("The search term 'Th1s i$ incorrect' is not valid." + "\n" +
"Name should start with a letter and can also contain numbers, dashes and spaces.", "red");
});
it("Should pass the target url to the 'open' package", async () => {
const openSpy = jasmine.createSpy("open").and.returnValue(Promise.resolve());
const moduleLoader = require("module");
const originalLoad = moduleLoader._load;
spyOn(moduleLoader, "_load").and.callFake(function (request: string, ...args: unknown[]) {
if (request === "open") {
return { __esModule: true, default: openSpy };
}
return originalLoad.call(this, request, ...args);
});
await doc.open("https://www.infragistics.com/search?q=igGrid");
expect(openSpy).toHaveBeenCalledTimes(1);
expect(openSpy).toHaveBeenCalledWith("https://www.infragistics.com/search?q=igGrid");
});
});
39 changes: 39 additions & 0 deletions spec/unit/igx-templates/grid-custom-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { App, Template } from "@igniteui/cli-core";
import * as path from "path";
import { requireFresh } from "../../helpers/utils";

const templatePath = path.join(__dirname, "../../../packages/igx-templates/igx-ts/grid/grid-custom");

describe("Unit - igx-ts Custom Grid template", () => {
let template: Template;

beforeAll(() => {
App.initialize();
});

beforeEach(() => {
// the template module exports a singleton that keeps state between calls
template = requireFresh<Template>(templatePath);
});

function generate(columnFeatures?: string[]): { [key: string]: any } {
if (columnFeatures) {
template.setExtraConfiguration({ columnFeatures });
}
return template.generateConfig("my grid");
}

it("does not enable grid filtering for sorting", () => {
const config = generate(["Sorting"]);

expect(config.columnFeatures).toBe(`[sortable]="true"`);
expect(config.gridFeatures).toBe("");
});

it("enables grid filtering for filtering", () => {
const config = generate(["Sorting", "Filtering"]);

expect(config.columnFeatures).toBe(`[sortable]="true" [filterable]="true"`);
expect(config.gridFeatures).toBe(`[allowFiltering]="true"`);
});
});
Loading
Loading