Skip to content

Completed redux-logic transition for linkGithubIdentity code#1672

Merged
outoftime merged 37 commits intopopcodeorg:masterfrom
jwang1919:jest
May 18, 2019
Merged

Completed redux-logic transition for linkGithubIdentity code#1672
outoftime merged 37 commits intopopcodeorg:masterfrom
jwang1919:jest

Conversation

@jwang1919
Copy link
Contributor

Followed same code conventions of when I did unlinkGithubIdentity. Replicated the same tests but in Jest and added a few more assertions.

Copy link
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@jwang1919 Nice work! Left some feedback, but it’s all either minor style nits or musings on my vision for the new test suite that you’d have had no way to anticipate : )


describe('linkGithubIdentity', () => {
test('success', async() => {
const mockCredential = {providerId: 'github.com'};
Copy link
Contributor

Choose a reason for hiding this comment

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

One thing that is really important to me as we build out this new test suite is that test data is always generated from a centralized, reusable place, rather than defined ad-hoc in test files. This was an ambition for the old test suite but it was not fully realized.

The specific approach I had in mind was this:

  • Create a __factories__ directory at the root of the project. This would have different submodules for different categories of test data:
    • __factories__/clients for data that comes from clients (such as mockCredential here, which comes from Firebase)
    • __factories__/state for data that comes from the Redux store
    • Maybe more categories will spring up
  • Use a factory definition library, probably Rosie, to define the factories (N.B. I think we want unregistered factories)
  • Use Jest’s moduleNameMapper configuration to map @factories to <rootDir>/__factories__ so we can do e.g. import {credential as createCredential} from '@factories/clients/firebase' without worrying about a bunch of ../.. nonsense

What do you think? Are you down to take this on? I was hoping to get some of the scaffolding set up myself so you wouldn’t have to deal with it, but you beat me to the first case of needing it : )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm... okay, that sounds okay with me. Never worked with Rosie before so will take a bit more time to complete this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I actually ended up running into a situation where I needed factories too… stay tuned, currently wrangling eslint 😭

const mockCredential = {providerId: 'github.com'};

linkGithub.mockResolvedValue({
user: {},
Copy link
Contributor

Choose a reason for hiding this comment

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

A corollary to the above is that I think all of our test data should be realistic, even if realism doesn’t seem important to the test as written. So I would propose using a factory here to generate a realistic Firebase user object as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

To answer your question the Firebase API docs are pretty good for figuring out the shape of a Firebase User; and again throwing a debugger or console.log() in the application code is a good way to see what the object actually looks like in a concrete instance.

test('credential already in use in experimental mode', async() => {
const error = new Error('credential already in use');
error.code = 'auth/credential-already-in-use';
error.credential = {providerId: 'github.com', accessToken: 'abc123'};
Copy link
Contributor

Choose a reason for hiding this comment

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

For avoidance of doubt I would include any client-generated error objects in the factories.

error.code = 'auth/credential-already-in-use';
error.credential = {providerId: 'github.com', accessToken: 'abc123'};

const githubProfile = {login: 'popcoder'};
Copy link
Contributor

Choose a reason for hiding this comment

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

Another one for the factories

@jwang1919
Copy link
Contributor Author

@outoftime Can this be merged? As discussed in chat the Rosie implementation will be coming later rather than sooner.

@outoftime
Copy link
Contributor

@jwang1919 it's not ideal to have this held up, but I think it's important not to introduce patterns into the new year suite that we don't want to see there in the long run—in this case, ad-hoc definition of test data. Once #1670 is merged, I think it should be pretty quick for you to add the factories you need

Cherry-picked from CodeMirror branch
@outoftime
Copy link
Contributor

@jwang1919 the CodeMirror branch is going to take a bit more work before it’s ready for primetime, so I cherry-picked over the bit that sets you up to write factories and pushed it to your branch here. I recommend checking out the documentation for rosie but you can also take a look at the factory I set up in the CodeMirror branch and the reasonably non-annoying way to import factories into jest tests employed therein.

@jwang1919
Copy link
Contributor Author

@outoftime okay. Used Rosie with linkGithubIdentityTest.js. My approach to getting Rosie to create an Error object was a bit tricky, so let me know if I'm heading in the right direction with this.
Also what would a realistic Firebase object look like so I can Rosie it?

Copy link
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@jwang1919 Rosie usage looking good! Left some comments on the details but the overall approach looks just right.


export const githubProfile = new Factory().attrs({
login: 'popcoder',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

The top-level principle for organizing factories should be where the data they’re generating would come from in the real application—in this case this profile object would come from the GitHub client, so this should live in __factories__/clients/github.js.

Also, as I mentioned before, we’ll want to generate factory data that is a reasonably complete representation of what the code we’re testing will see. I don’t necessarily think we need to capture every property of large objects like a GitHub profile, but we should try to capture a subset that generously covers all the properties Popcode might care about (this is a bit subjective, but I trust your judgement). As for where to find that information, API docs are probably your best bet; throwing a debugger or a console.log in the application code and then capturing a real example is another fine approach.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this is still outstanding?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Huh, I thought I changed this already. I'll check it out again.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, to be clear—this looks good (very complete!) but it belongs in a __factories__/clients/github.js module because it is synthesizing GitHub client data, not Firebase client data.


export const firebaseError = Factory.define(
'firebaseError',
FirebaseError,
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like the right approach to me! 👍

const mockCredential = {providerId: 'github.com'};

linkGithub.mockResolvedValue({
user: {},
Copy link
Contributor

Choose a reason for hiding this comment

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

To answer your question the Firebase API docs are pretty good for figuring out the shape of a Firebase User; and again throwing a debugger or console.log() in the application code is a good way to see what the object actually looks like in a concrete instance.

Copy link
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@jwang1919 looks like still a handful of lint errors—let me know if you get stuck with the import one, that plugin has been a Major Payne with the factory setup. i can jump in.

btw you know you don’t have to push and wait for Travis to run to see test results, right? you can run yarn test to get the whole thing, or yarn lint just to see lint errors…


export const githubProfile = new Factory().attrs({
login: 'popcoder',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this is still outstanding?

@jwang1919
Copy link
Contributor Author

So the lint errors seem to only be showing up in Travis but not when I run yarn test.
Ex.
On this line, I added a comment to hide the jslint errors and warnings. yarn test passes for me, but when it Travis thinks it is no bueno.
https://github.com/jwang1919/popcode/blob/jest/src/logic/__tests__/linkGithubIdentityTest.js#L7

@jwang1919
Copy link
Contributor Author

@outoftime anyway yeah I need help, Major Payne is kicking my ass.

outoftime added 2 commits May 9, 2019 19:41
* master:
  Archive projects  (popcodeorg#1485)
As expected, `eslint-plugin-import` released a fix that corrects the
behavior with internal modules that use module lookup aliases. So now
the modules aliased under `@factory` are correctly recognized as
internal.
@outoftime
Copy link
Contributor

@jwang1919 got u

Copy link
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@jwang1919 all looks good aside from moving that one factory! (and the one test desc)


export const githubProfile = new Factory().attrs({
login: 'popcoder',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, to be clear—this looks good (very complete!) but it belongs in a __factories__/clients/github.js module because it is synthesizing GitHub client data, not Firebase client data.

expect(user).toEqual(mockUser);
});

test('credential already in use in experimental mode', async() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

You can drop the “in experimental mode” from this, that’s an outdated description in the old test.

@outoftime
Copy link
Contributor

@jwang1919 looks like you might have forgotten to commit the new factory?

@jwang1919
Copy link
Contributor Author

Oops! My bad.

@outoftime outoftime merged commit 60357cb into popcodeorg:master May 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants