Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(angular): switch to using jasmine-marbles for certain symbols
- Loading branch information
Showing
7 changed files
with
232 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,6 @@ | |
"chalk", | ||
"chokidar", | ||
"ignore", | ||
"jasmine-marbles", | ||
"minimatch", | ||
"rxjs-for-await", | ||
"webpack-merge", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
packages/angular/src/migrations/update-15-0-0/switch-to-jasmine-marbles.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import switchToJasmineMarbles from './switch-to-jasmine-marbles'; | ||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; | ||
import { readJson } from '@nrwl/devkit'; | ||
import { jasmineMarblesVersion } from '../../utils/versions'; | ||
|
||
describe('switchToJasmineMarbles', () => { | ||
it('should correctly migrate a file that is using imports from nrwl/angular/testing that exist in jasmine-marbles', () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(); | ||
tree.write( | ||
'a/b/mytest.spec.ts', | ||
`import {hot, cold} from '@nrwl/angular/testing';` | ||
); | ||
tree.write( | ||
'c/d/mytest.spec.ts', | ||
`import {hot, getTestScheduler} from '@nrwl/angular/testing';` | ||
); | ||
tree.write( | ||
'e/mytest.spec.ts', | ||
`import {getTestScheduler, time} from '@nrwl/angular/testing';` | ||
); | ||
|
||
// ACT | ||
switchToJasmineMarbles(tree); | ||
|
||
// ASSERT | ||
expect(tree.read('a/b/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
" | ||
import {hot,cold} from 'jasmine-marbles';" | ||
`); | ||
expect(tree.read('c/d/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
" | ||
import {hot,getTestScheduler} from 'jasmine-marbles';" | ||
`); | ||
expect(tree.read('e/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
" | ||
import {getTestScheduler,time} from 'jasmine-marbles';" | ||
`); | ||
}); | ||
|
||
it('should correctly migrate and split imports from nrwl/angular/testing that exist in jasmine-marbles and nrwl/angular/testing', () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(); | ||
tree.write( | ||
'a/b/mytest.spec.ts', | ||
`import {hot, cold, readFirst} from '@nrwl/angular/testing';` | ||
); | ||
tree.write( | ||
'c/d/mytest.spec.ts', | ||
`import {hot, getTestScheduler, readAll} from '@nrwl/angular/testing';` | ||
); | ||
tree.write( | ||
'e/mytest.spec.ts', | ||
`import {getTestScheduler, time, readAll, readFirst} from '@nrwl/angular/testing';` | ||
); | ||
|
||
// ACT | ||
switchToJasmineMarbles(tree); | ||
|
||
// ASSERT | ||
expect(tree.read('a/b/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
"import {readFirst} from '@nrwl/angular/testing'; | ||
import {hot,cold} from 'jasmine-marbles';" | ||
`); | ||
expect(tree.read('c/d/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
"import {readAll} from '@nrwl/angular/testing'; | ||
import {hot,getTestScheduler} from 'jasmine-marbles';" | ||
`); | ||
expect(tree.read('e/mytest.spec.ts', 'utf-8')).toMatchInlineSnapshot(` | ||
"import {readAll,readFirst} from '@nrwl/angular/testing'; | ||
import {getTestScheduler,time} from 'jasmine-marbles';" | ||
`); | ||
}); | ||
|
||
it('should add jasmine-marbles as a dependency if it does not exist but uses jasmine-marbles symbols in files', () => { | ||
// ARRANGE | ||
const tree = createTreeWithEmptyWorkspace(); | ||
tree.write( | ||
'a/b/mytest.spec.ts', | ||
`import {hot, cold, readFirst} from '@nrwl/angular/testing';` | ||
); | ||
|
||
// ACT | ||
switchToJasmineMarbles(tree); | ||
|
||
// ASSERT | ||
|
||
const jasmineMarblesDependency = readJson(tree, 'package.json') | ||
.devDependencies['jasmine-marbles']; | ||
expect(jasmineMarblesDependency).toBeTruthy(); | ||
expect(jasmineMarblesDependency).toBe(jasmineMarblesVersion); | ||
}); | ||
}); |
132 changes: 132 additions & 0 deletions
132
packages/angular/src/migrations/update-15-0-0/switch-to-jasmine-marbles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import type { Tree } from '@nrwl/devkit'; | ||
import { | ||
addDependenciesToPackageJson, | ||
readJson, | ||
visitNotIgnoredFiles, | ||
} from '@nrwl/devkit'; | ||
import { extname } from 'path'; | ||
import { tsquery } from '@phenomnomnominal/tsquery'; | ||
import { jasmineMarblesVersion } from '@nrwl/angular/src/utils/versions'; | ||
|
||
export default function switchToJasmineMarbles(tree: Tree) { | ||
const usesJasmineMarbles = replaceJasmineMarbleUsagesInFiles(tree); | ||
addJasmineMarblesDevDependencyIfUsed(tree, usesJasmineMarbles); | ||
} | ||
|
||
function replaceJasmineMarbleUsagesInFiles(tree: Tree) { | ||
let usesJasmineMarbles = false; | ||
|
||
visitNotIgnoredFiles(tree, '/', (path) => { | ||
if (extname(path) !== '.ts') { | ||
return; | ||
} | ||
|
||
const fileContents = tree.read(path, 'utf-8'); | ||
if (!fileContents.includes('@nrwl/angular/testing')) { | ||
return; | ||
} | ||
|
||
const NRWL_ANGULAR_TESTING_IMPORT_SELECTOR = | ||
'ImportDeclaration:has(StringLiteral[value="@nrwl/angular/testing"])'; | ||
const ast = tsquery.ast(fileContents); | ||
const nrwlAngularTestingImportNodes = tsquery( | ||
ast, | ||
NRWL_ANGULAR_TESTING_IMPORT_SELECTOR, | ||
{ visitAllChildren: true } | ||
); | ||
|
||
if ( | ||
!nrwlAngularTestingImportNodes || | ||
nrwlAngularTestingImportNodes.length === 0 | ||
) { | ||
return; | ||
} | ||
|
||
const jasmineMarblesExportsRegex = new RegExp( | ||
/(hot|cold|getTestScheduler|time)/ | ||
); | ||
if ( | ||
!jasmineMarblesExportsRegex.test( | ||
nrwlAngularTestingImportNodes[0].getText() | ||
) | ||
) { | ||
return; | ||
} | ||
|
||
const IMPORT_SPECIFIERS_SELECTOR = 'NamedImports > ImportSpecifier'; | ||
const importSpecifierNodes = tsquery( | ||
nrwlAngularTestingImportNodes[0], | ||
IMPORT_SPECIFIERS_SELECTOR, | ||
{ visitAllChildren: true } | ||
); | ||
|
||
if (!importSpecifierNodes || importSpecifierNodes.length === 0) { | ||
return; | ||
} | ||
|
||
const validNrwlTestingImports = []; | ||
const validJasmineMarbleImports = []; | ||
for (const node of importSpecifierNodes) { | ||
const importSymbol = node.getText(); | ||
if (jasmineMarblesExportsRegex.test(importSymbol)) { | ||
validJasmineMarbleImports.push(importSymbol); | ||
} else { | ||
validNrwlTestingImports.push(importSymbol); | ||
} | ||
} | ||
|
||
if (!usesJasmineMarbles && validJasmineMarbleImports.length > 0) { | ||
usesJasmineMarbles = true; | ||
} | ||
|
||
const newFileContents = `${fileContents.slice( | ||
0, | ||
nrwlAngularTestingImportNodes[0].getStart() | ||
)}${ | ||
validNrwlTestingImports.length > 0 | ||
? `import {${validNrwlTestingImports.join( | ||
',' | ||
)}} from '@nrwl/angular/testing';` | ||
: '' | ||
} | ||
${ | ||
validJasmineMarbleImports.length > 0 | ||
? `import {${validJasmineMarbleImports.join( | ||
',' | ||
)}} from 'jasmine-marbles';${fileContents.slice( | ||
nrwlAngularTestingImportNodes[0].getEnd(), | ||
-1 | ||
)}` | ||
: '' | ||
}`; | ||
|
||
tree.write(path, newFileContents); | ||
}); | ||
return usesJasmineMarbles; | ||
} | ||
|
||
function addJasmineMarblesDevDependencyIfUsed( | ||
tree: Tree, | ||
usesJasmineMarbles: boolean | ||
) { | ||
if (!usesJasmineMarbles) { | ||
return; | ||
} | ||
|
||
const pkgJson = readJson(tree, 'package.json'); | ||
const jasmineMarblesDependency = pkgJson.dependencies['jasmine-marbles']; | ||
const jasmineMarblesDevDependency = | ||
pkgJson.devDependencies['jasmine-marbles']; | ||
|
||
if (jasmineMarblesDependency || jasmineMarblesDevDependency) { | ||
return; | ||
} | ||
|
||
addDependenciesToPackageJson( | ||
tree, | ||
{}, | ||
{ | ||
'jasmine-marbles': jasmineMarblesVersion, | ||
} | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1 @@ | ||
import { | ||
cold as rxjsMarblesCold, | ||
hot as rxjsMarblesHot, | ||
getTestScheduler as rxjsMarblesTestScheduler, | ||
time as rxjsMarblesTime, | ||
} from 'jasmine-marbles'; | ||
|
||
/** | ||
* @deprecated Import from 'jasmine-marbles' instead. Will be removed in Nx v15. | ||
*/ | ||
export const cold = rxjsMarblesCold; | ||
/** | ||
* @deprecated Import from 'jasmine-marbles' instead. Will be removed in Nx v15. | ||
*/ | ||
export const hot = rxjsMarblesHot; | ||
/** | ||
* @deprecated Import from 'jasmine-marbles' instead. Will be removed in Nx v15. | ||
*/ | ||
export const getTestScheduler = rxjsMarblesTestScheduler; | ||
/** | ||
* @deprecated Import from 'jasmine-marbles' instead. Will be removed in Nx v15. | ||
*/ | ||
export const time = rxjsMarblesTime; | ||
|
||
export { readAll, readFirst } from './src/testing-utils'; |