Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code tightening (prepping for Angular 8) #1212

Merged
merged 7 commits into from
Aug 13, 2019
Merged

Conversation

msorens
Copy link
Contributor

@msorens msorens commented Aug 11, 2019

🔩 Description: What code changed, and why?

In an effort to make the upcoming PR for the Angular 8 upgrade smaller, I undertook to clean up many of the deprecation, lint, compiler, and test errors that are due to more stringent checks. So all of the changes herein are compatible with our existing Angular/rxjs/TypeScript versions. Some of them correct errors in the code base that went unreported and, being somewhat innocuous, unnoticed.

Follow the commits if you want to see each type of change in isolation.
However, I have also added pre-review comments on the first occurrence of each category so it is easy to review from the file changes, too.

⛓️ Related Resources

👍 Definition of Done

Compiler, lint, and unit tests all still report no issues.

👟 How to Build and Test the Change

Rebuild automate-ui.
Run unit tests.
Run lint.

@msorens msorens added automate-ui chore auth-team anything that needs to be on the auth team board labels Aug 11, 2019
@msorens msorens requested review from scottopherson and a team August 11, 2019 18:43
@msorens msorens self-assigned this Aug 11, 2019
.pipe(
mergeMap(([_action, version]) =>
mergeMap(([_action, version]: [GetAllTokens, IAMMajorVersion]) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated variant of combineLatest:

combineLatest is deprecated: Pass arguments in a single array instead `combineLatest([a, b, c])`

So ostensibly the only change is adding the square brackets around all the arguments in combineLatest. In practice, however, it uncovered an issue: Each of the arguments (in this case _action and version had types inferred, but they were both assigned the type of the first argument in the array (GetAllTokens). Thus it is necessary here to enumerate the explicit types on L55 (and similarly throughout).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 That's a bummer, I thought exactly these kinds of type inference improvements where coming with the bump... but wait, you're not saying that this isn't the case, you're just saying that on our current version of angular (or rather ngrx), the inference is wrong. Do you know something about the post-upgrade situation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, definitely a bummer... Unfortunately, post-upgrade has the same problem here.

@@ -8,7 +8,7 @@ export const userpermsState = createFeatureSelector<PermEntityState>(NGRX_REDUCE

export const permList = createSelector(
userpermsState,
(state) => map((id) => get(['byId', id], state),
(state) => map((id: string) => get(['byId', id], state),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some places, like this, could not infer a type, so needed an explicit type added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Is there a way to lint for something like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post-upgrade, it shows up either as a lint error or compiler error; I don't recall which.

@@ -30,12 +34,12 @@ describe('ServerOrgFilterSidebarComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ServerOrgFilterSidebarComponent);
component = fixture.componentInstance;
this.ngrxStore = TestBed.get(Store);
ngrxStore = TestBed.get(Store);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An interesting set of unit test failures here. Apparently, our current code allows this on-the-fly creating of this.ngrxStore when we don't really even have a this object here in the test code(!). That does not fly, however, with the Angular 8 env, so made it an explicit local variable on L15.

@@ -31,7 +31,7 @@ describe('SidebarSelectListComponent', () => {
it('interprets the label correctly', () => {
component.label = 'Servers';

component.allItemsObs = Observable.create((observer: Observer<Array<string>>) => {
component.allItemsObs = new Observable((observer: Observer<Array<string>>) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated method:

create is deprecated: use new Observable() instead

This is a non-complicated change; literally just do what the error says--because our uses of create conform to the necessary pattern already.

this.sendFiles(Array.from(event.target.files)).subscribe({
next: fileUploads => { this.fileUploads = fileUploads; },
error: null,
complete: () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated variant of subscribe:

subscribe is deprecated: Use an observer instead of a complete callback

That message is misleading; subscribe is not wholly deprecated. The developers thought there were too many signatures for its own good (see ReactiveX/rxjs#4159), so instead of using this (with three arguments)...

subscribe(next, err, complete) 

one needs to pass in a single argument (an "observer") like this:

subscribe({next: f1, err: f2, complete: f3})

That format also happens to make it simpler if you do not need to supply all three callbacks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 So, I think you mean error in the last code block. But from what you say, it's not required to supply something that's not need -- so, I wonder why we'd put error: null into line 217.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, you're correct; that was just mechanical on my part, but don't need the error: null.

takeUntil(this.isDestroyed),
map(([gStatus, uStatus, gpStatus]: string[]) => {
map(([gStatus, uStatus, gpStatus]) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not technically strings; they are of type EntityStatus which is a constrained set of strings. So I could have just done this:

map(([gStatus, uStatus, gpStatus]: EntityStatus[]) => {

But, all the arguments are the same type (see my earlier note where there were different types), so the types are correctly inferred, and there is thus no need to add an explicit type here; it would be redundant.

private currentFieldDirection: SortDirection;
private currentSortField: string;
public currentFieldDirection: SortDirection;
public currentSortField: string;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting to note that these were used in some unit tests--even though they were private!--with no complaint in our current environment. But the upgrade will get more particular, requiring this fix.

@@ -36,7 +36,7 @@ describe('HttpClientAuthInterceptor', () => {

it('when a 401 response is intercepted logs out the session', done => {
spyOn(chefSession, 'logout');
httpClient.get('/endpoint').subscribe(null, done);
httpClient.get('/endpoint').subscribe({ error: done });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a good example showing why the "observer object" is better than separate arguments ("next, error, complete" in that order). This test wants to ignore the next callback, so it gave a null. It then wants to provide an error callback, because the http call is expected to fail, and that is the jasmine done. So in the revised code, we just provide the error callback--no guesswork involved.

'percent': 'percent',
'status': 'status',
'percent': 25,
'status': 1,
'response': 'response'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, so much for strict typing... these types were plain wrong, yet our current env does not complain.


export interface AuthorizedProjectsResponse {
projects: string[];
projects: Project[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa! Another interesting type that should never have passed muster.

@msorens msorens force-pushed the ms/angular-code-tightening branch from 7bcd135 to 8649d98 Compare August 12, 2019 04:23
Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pushing this forward. Some questions/discussion items inline 🙃

.pipe(
mergeMap(([_action, version]) =>
mergeMap(([_action, version]: [GetAllTokens, IAMMajorVersion]) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 That's a bummer, I thought exactly these kinds of type inference improvements where coming with the bump... but wait, you're not saying that this isn't the case, you're just saying that on our current version of angular (or rather ngrx), the inference is wrong. Do you know something about the post-upgrade situation?

@@ -6,7 +6,7 @@ import { environment as env } from 'environments/environment';
import { Role } from './role.model';

export interface RolesResponse {
policies: Role[];
roles: Role[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me think we're using this wrong. Why did this not blow up somewhere?

@@ -8,7 +8,7 @@ export const userpermsState = createFeatureSelector<PermEntityState>(NGRX_REDUCE

export const permList = createSelector(
userpermsState,
(state) => map((id) => get(['byId', id], state),
(state) => map((id: string) => get(['byId', id], state),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Is there a way to lint for something like this?

this.sendFiles(Array.from(event.target.files)).subscribe({
next: fileUploads => { this.fileUploads = fileUploads; },
error: null,
complete: () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 So, I think you mean error in the last code block. But from what you say, it's not required to supply something that's not need -- so, I wonder why we'd put error: null into line 217.

.subscribe(([nodeCounts, filterCount]) => {
.subscribe((values: any[]) => {
const nodeCounts: NodeCount = values[0];
const filterCount: number = values[1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But subscribe did not take kindly when I tried the usual fix [...]

What happened? Did it throw you out? 😉

Fixes this warning from the impending Angular 8 upgrade:
"create is deprecated: use new Observable() instead"

Fix:
Change Observable.create(... to new Observable(...

Signed-off-by: michael sorens <[email protected]>
Fixes this warning from the impending Angular 8 upgrade:
"subscribe is deprecated: Use an observer instead of a ... callback"

Fix:
Change subscribe(next, err, complete) => subscribe({next: f1, err: f2, complete: f3})

Reference:
https://stackoverflow.com/a/56985787/115690

Signed-off-by: michael sorens <[email protected]>
Fixes this warning from the impending Angular 8 upgrade:
"combineLatest is deprecated: Pass arguments in a single array instead `combineLatest([a, b, c])`"

Fix:
Change  combineLatest(...) => combineLatest([...])

Signed-off-by: michael sorens <[email protected]>
New version of Typescript is apparently smarter
so found some issues, but just a few!

Signed-off-by: michael sorens <[email protected]>
These all caused failures in the Angular 8 environment.

Signed-off-by: michael sorens <[email protected]>
Signed-off-by: michael sorens <[email protected]>
@msorens msorens force-pushed the ms/angular-code-tightening branch from 9999777 to fbdbf17 Compare August 12, 2019 16:42
Copy link
Contributor

@tarablack01 tarablack01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msorens Love it! LGTM 👍🏻

@msorens msorens merged commit 8a101d1 into master Aug 13, 2019
@msorens msorens deleted the ms/angular-code-tightening branch August 13, 2019 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth-team anything that needs to be on the auth team board automate-ui chore
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants