Skip to content

Commit 7565f2d

Browse files
Ashok Tamangalxhub
authored andcommitted
feat: add features in get-dependent-files.ts (angular#1525)
add logic to filter out spec file associated with the given component unit and all index files while getting all dependent files add utlity function to get all the files (.html/stylesheets/.spec.ts) associated with the given component unit change the constructor method of the class ModuleResolver (add 'rootPath' as an additional parameter)
1 parent 539c57d commit 7565f2d

File tree

4 files changed

+114
-16
lines changed

4 files changed

+114
-16
lines changed

addon/ng2/utilities/get-dependent-files.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,37 @@ export function hasIndexFile(dirPath: string): Promise<Boolean> {
7474
});
7575
}
7676

77+
/**
78+
* Function to get all the templates, stylesheets, and spec files of a given component unit
79+
* Assumption: When any component/service/pipe unit is generated, Angular CLI has a blueprint for
80+
* creating associated files with the name of the generated unit. So, there are two
81+
* assumptions made:
82+
* a. the function only returns associated files that have names matching to the given unit.
83+
* b. the function only looks for the associated files in the directory where the given unit
84+
* exists.
85+
*
86+
* @todo read the metadata to look for the associated files of a given file.
87+
*
88+
* @param fileName
89+
*
90+
* @return absolute paths of '.html/.css/.sass/.spec.ts' files associated with the given file.
91+
*
92+
*/
93+
export function getAllAssociatedFiles(fileName: string): Promise<string[]> {
94+
let fileDirName = path.dirname(fileName);
95+
let componentName = path.basename(fileName, '.ts');
96+
const globSearch = denodeify(glob);
97+
return globSearch(path.join(fileDirName, `${componentName}.*`), { nodir: true })
98+
.then((files: string[]) => {
99+
return files.filter((file) => {
100+
return (path.basename(file) !== 'index.ts');
101+
});
102+
});
103+
}
104+
77105
/**
78106
* Returns a map of all dependent file/s' path with their moduleSpecifier object
79-
* (specifierText, pos, end)
107+
* (specifierText, pos, end).
80108
*
81109
* @param fileName file upon which other files depend
82110
* @param rootPath root of the project
@@ -86,7 +114,7 @@ export function hasIndexFile(dirPath: string): Promise<Boolean> {
86114
*/
87115
export function getDependentFiles(fileName: string, rootPath: string): Promise<ModuleMap> {
88116
const globSearch = denodeify(glob);
89-
return globSearch(path.join(rootPath, '**/*.*.ts'), { nodir: true })
117+
return globSearch(path.join(rootPath, '**/*.ts'), { nodir: true })
90118
.then((files: string[]) => Promise.all(files.map(file => createTsSourceFile(file)))
91119
.then((tsFiles: ts.SourceFile[]) => tsFiles.map(file => getImportClauses(file)))
92120
.then((moduleSpecifiers: ModuleImport[][]) => {

addon/ng2/utilities/module-resolver.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ import * as dependentFilesUtils from './get-dependent-files';
77
import { Promise } from 'es6-promise';
88
import { Change, ReplaceChange } from './change';
99

10-
// The root directory of Angular Project.
11-
const ROOT_PATH = path.resolve('src/app');
12-
1310
/**
1411
* Rewrites import module of dependent files when the file is moved.
1512
* Also, rewrites export module of related index file of the given file.
1613
*/
1714
export class ModuleResolver {
1815

19-
constructor(public oldFilePath: string, public newFilePath: string) {}
16+
constructor(public oldFilePath: string, public newFilePath: string, public rootPath: string) {}
2017

2118
/**
2219
* Changes are applied from the bottom of a file to the top.
@@ -54,10 +51,19 @@ export class ModuleResolver {
5451
* @return {Promise<Change[]>}
5552
*/
5653
resolveDependentFiles(): Promise<Change[]> {
57-
return dependentFilesUtils.getDependentFiles(this.oldFilePath, ROOT_PATH)
54+
return dependentFilesUtils.getDependentFiles(this.oldFilePath, this.rootPath)
5855
.then((files: dependentFilesUtils.ModuleMap) => {
5956
let changes: Change[] = [];
60-
Object.keys(files).forEach(file => {
57+
let fileBaseName = path.basename(this.oldFilePath, '.ts');
58+
// Filter out the spec file associated with to-be-promoted component unit.
59+
let relavantFiles = Object.keys(files).filter((file) => {
60+
if (path.extname(path.basename(file, '.ts')) === '.spec') {
61+
return path.basename(path.basename(file, '.ts'), '.spec') !== fileBaseName;
62+
} else {
63+
return true;
64+
}
65+
});
66+
relavantFiles.forEach(file => {
6167
let tempChanges: ReplaceChange[] = files[file]
6268
.map(specifier => {
6369
let componentName = path.basename(this.oldFilePath, '.ts');

tests/acceptance/get-dependent-files.spec.ts

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ describe('Get Dependent Files: ', () => {
1616
'foo': {
1717
'foo.component.ts': `import * from '../bar/baz/baz.component'
1818
import * from '../bar/bar.component'`,
19+
'foo.component.html': '',
20+
'foo.component.css': '',
21+
'foo.component.spec.ts': '',
22+
'foo.ts': '',
1923
'index.ts': `export * from './foo.component'`
2024
},
2125
'bar': {
@@ -24,12 +28,23 @@ describe('Get Dependent Files: ', () => {
2428
'baz.html': '<h1> Hello </h1>'
2529
},
2630
'bar.component.ts': `import * from './baz/baz.component'
27-
import * from '../foo'`
31+
import * from '../foo'`,
32+
'bar.component.spec.ts': ''
2833
},
2934
'foo-baz': {
30-
'no-module.component.ts': ''
35+
'no-module.component.ts': '',
36+
'no-module.component.spec.ts': 'import * from "../bar/bar.component";'
3137
},
32-
'empty-dir': {}
38+
'quux': {
39+
'quux.ts': '',
40+
'quux.html': '',
41+
'quux.css': '',
42+
'quux.spec.ts': ''
43+
},
44+
'noAngular.tag.ts': '',
45+
'noAngular.tag.html': '',
46+
'noAngular.tag.sass': '',
47+
'noAngular.tag.spec.ts': '',
3348
}
3449
};
3550
mockFs(mockDrive);
@@ -102,13 +117,56 @@ describe('Get Dependent Files: ', () => {
102117
});
103118
});
104119

120+
describe('returns an array of all the associated files of a given component unit.', () => {
121+
it('when the component name has a special Angular tag(component/pipe/service)', () => {
122+
let sourceFile = path.join(rootPath, 'foo/foo.component.ts');
123+
return dependentFilesUtils.getAllAssociatedFiles(sourceFile)
124+
.then((files: string[]) => {
125+
let expectedContents = [
126+
'src/app/foo/foo.component.css',
127+
'src/app/foo/foo.component.html',
128+
'src/app/foo/foo.component.spec.ts',
129+
'src/app/foo/foo.component.ts'
130+
];
131+
assert.deepEqual(files, expectedContents);
132+
});
133+
});
134+
it('when the component name has non-Angular tag', () => {
135+
let sourceFile = path.join(rootPath, 'noAngular.tag.ts');
136+
return dependentFilesUtils.getAllAssociatedFiles(sourceFile)
137+
.then((files: string[]) => {
138+
let expectedContents = [
139+
'src/app/noAngular.tag.html',
140+
'src/app/noAngular.tag.sass',
141+
'src/app/noAngular.tag.spec.ts',
142+
'src/app/noAngular.tag.ts'
143+
];
144+
assert.deepEqual(files, expectedContents);
145+
});
146+
});
147+
it('when the component name has no tag after the unique file name', () => {
148+
let sourceFile = path.join(rootPath, 'quux/quux.ts');
149+
return dependentFilesUtils.getAllAssociatedFiles(sourceFile)
150+
.then((files: string[]) => {
151+
let expectedContents = [
152+
'src/app/quux/quux.css',
153+
'src/app/quux/quux.html',
154+
'src/app/quux/quux.spec.ts',
155+
'src/app/quux/quux.ts'
156+
];
157+
assert.deepEqual(files, expectedContents);
158+
});
159+
});
160+
});
161+
105162
describe('returns a map of all files which depend on a given file ', () => {
106163
it('when the given component unit has no index file', () => {
107164
let sourceFile = path.join(rootPath, 'bar/bar.component.ts');
108165
return dependentFilesUtils.getDependentFiles(sourceFile, rootPath)
109166
.then((contents: dependentFilesUtils.ModuleMap) => {
110167
let bazFile = path.join(rootPath, 'bar/baz/baz.component.ts');
111168
let fooFile = path.join(rootPath, 'foo/foo.component.ts');
169+
let noModuleSpecFile = path.join(rootPath, 'foo-baz/no-module.component.spec.ts');
112170
let expectedContents: dependentFilesUtils.ModuleMap = {};
113171
expectedContents[bazFile] = [{
114172
specifierText: '../bar.component',
@@ -120,6 +178,11 @@ describe('Get Dependent Files: ', () => {
120178
pos: 85,
121179
end: 108
122180
}];
181+
expectedContents[noModuleSpecFile] = [{
182+
specifierText: '../bar/bar.component',
183+
pos: 13,
184+
end: 36
185+
}];
123186
assert.deepEqual(contents, expectedContents);
124187
});
125188
});

tests/acceptance/module-resolver.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ describe('ModuleResolver', () => {
2222
'baz': {
2323
'baz.component.ts': `import * from "../bar.component"
2424
import * from '../../foo-baz/qux/quux/foobar/foobar.component'
25-
`
25+
`,
26+
'baz.component.spec.ts': 'import * from "./baz.component";'
2627
},
2728
'bar.component.ts': `import * from './baz/baz.component'
2829
import * from '../foo/foo.component'`,
@@ -64,7 +65,7 @@ describe('ModuleResolver', () => {
6465
it('when there is no index.ts in oldPath', () => {
6566
let oldFilePath = path.join(rootPath, 'bar/baz/baz.component.ts');
6667
let newFilePath = path.join(rootPath, 'foo');
67-
let resolver = new ModuleResolver(oldFilePath, newFilePath);
68+
let resolver = new ModuleResolver(oldFilePath, newFilePath, rootPath);
6869
return resolver.resolveDependentFiles()
6970
.then((changes) => resolver.applySortedChangePromise(changes))
7071
.then(() => dependentFilesUtils.createTsSourceFile(barFile))
@@ -93,7 +94,7 @@ describe('ModuleResolver', () => {
9394
it('when no files are importing the given file', () => {
9495
let oldFilePath = path.join(rootPath, 'foo-baz/foo-baz.component.ts');
9596
let newFilePath = path.join(rootPath, 'bar');
96-
let resolver = new ModuleResolver(oldFilePath, newFilePath);
97+
let resolver = new ModuleResolver(oldFilePath, newFilePath, rootPath);
9798
return resolver.resolveDependentFiles()
9899
.then((changes) => resolver.applySortedChangePromise(changes))
99100
.then(() => resolver.resolveOwnImports())
@@ -108,7 +109,7 @@ describe('ModuleResolver', () => {
108109
it('when oldPath and newPath both do not have index.ts', () => {
109110
let oldFilePath = path.join(rootPath, 'bar/baz/baz.component.ts');
110111
let newFilePath = path.join(rootPath, 'foo-baz');
111-
let resolver = new ModuleResolver(oldFilePath, newFilePath);
112+
let resolver = new ModuleResolver(oldFilePath, newFilePath, rootPath);
112113
return resolver.resolveDependentFiles()
113114
.then((changes) => resolver.applySortedChangePromise(changes))
114115
.then(() => dependentFilesUtils.createTsSourceFile(barFile))
@@ -137,7 +138,7 @@ describe('ModuleResolver', () => {
137138
it('when there are multiple spaces between symbols and specifier', () => {
138139
let oldFilePath = path.join(rootPath, 'foo-baz/qux/quux/foobar/foobar.component.ts');
139140
let newFilePath = path.join(rootPath, 'foo');
140-
let resolver = new ModuleResolver(oldFilePath, newFilePath);
141+
let resolver = new ModuleResolver(oldFilePath, newFilePath, rootPath);
141142
return resolver.resolveDependentFiles()
142143
.then((changes) => resolver.applySortedChangePromise(changes))
143144
.then(() => dependentFilesUtils.createTsSourceFile(fooQuxFile))

0 commit comments

Comments
 (0)