Skip to content

Commit 5094cd6

Browse files
Thanatos9404alan-agius4
authored andcommitted
fix(@angular-devkit/schematics): support delegating trees in the filter rule (#34539)
`filter()` only accepted a `HostTree` and threw "Tree type is not supported." for any other tree. A `UnitTestTree` is a `DelegateTree` around a `HostTree`, so a schematic that uses `filter()` failed in unit tests when run on the tree returned by a previous `runSchematic` call. Unwrap delegating trees and filter the `HostTree` they wrap. Closes #26000 PR Close #34539
1 parent a8dbf9d commit 5094cd6

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

‎packages/angular_devkit/schematics/src/rules/base.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import { concat, lastValueFrom, map, mapTo, toArray } from 'rxjs';
1010
import { FileOperator, Rule, Source } from '../engine/interface';
1111
import { SchematicsException } from '../exception/exception';
12+
import { DelegateTree } from '../tree/delegate';
1213
import { FilterHostTree, HostTree } from '../tree/host-tree';
1314
import { FileEntry, FilePredicate, MergeStrategy, Tree } from '../tree/interface';
1415
import { ScopedTree } from '../tree/scoped';
@@ -74,6 +75,10 @@ export function noop(): Rule {
7475

7576
export function filter(predicate: FilePredicate<boolean>): Rule {
7677
return (tree: Tree) => {
78+
if (tree instanceof DelegateTree) {
79+
tree = tree.branch();
80+
}
81+
7782
if (HostTree.isHostTree(tree)) {
7883
return new FilterHostTree(tree, predicate);
7984
} else {

‎packages/angular_devkit/schematics/src/rules/base_spec.ts‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
import { Path, virtualFs } from '@angular-devkit/core';
1010
import { lastValueFrom, of as observableOf } from 'rxjs';
11+
import { UnitTestTree } from '../../testing';
1112
import { Rule, SchematicContext, Source } from '../engine/interface';
1213
import { HostTree } from '../tree/host-tree';
1314
import { MergeStrategy, Tree } from '../tree/interface';
1415
import { empty } from '../tree/static';
15-
import { apply, applyToSubtree, chain, partitionApplyMerge } from './base';
16+
import { apply, applyToSubtree, chain, filter, partitionApplyMerge } from './base';
1617
import { callRule, callSource } from './call';
1718
import { move } from './move';
1819

@@ -242,3 +243,37 @@ describe('applyToSubtree', () => {
242243
expect(result.exists('a/c/file3')).toBe(true);
243244
});
244245
});
246+
247+
describe('filter', () => {
248+
it('works with a HostTree', async () => {
249+
const tree = new HostTree();
250+
tree.create('/file1.ts', '');
251+
tree.create('/file2.js', '');
252+
253+
const result = await lastValueFrom(
254+
callRule(
255+
filter((path) => path.endsWith('.ts')),
256+
observableOf(tree),
257+
context,
258+
),
259+
);
260+
expect(result.exists('/file1.ts')).toBe(true);
261+
expect(result.exists('/file2.js')).toBe(false);
262+
});
263+
264+
it('works with a UnitTestTree', async () => {
265+
const tree = new HostTree();
266+
tree.create('/file1.ts', '');
267+
tree.create('/file2.js', '');
268+
269+
const result = await lastValueFrom(
270+
callRule(
271+
filter((path) => path.endsWith('.ts')),
272+
observableOf(new UnitTestTree(new UnitTestTree(tree))),
273+
context,
274+
),
275+
);
276+
expect(result.exists('/file1.ts')).toBe(true);
277+
expect(result.exists('/file2.js')).toBe(false);
278+
});
279+
});

0 commit comments

Comments
 (0)