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

Make add-on reducer state more explicit #3073

Merged
merged 30 commits into from
Sep 7, 2017

Conversation

kumar303
Copy link
Contributor

@kumar303 kumar303 commented Sep 6, 2017

Fixes mozilla/addons#10708

This will hopefully make the central add-on reducer easier to deal with for features and bug fixes but it has potential to break a lot of stuff. It would help if you could test out add-on/theme installs. I've manually tested AMO and the Discopane.

@codecov-io
Copy link

codecov-io commented Sep 6, 2017

Codecov Report

Merging #3073 into master will increase coverage by 0.04%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    mozilla/addons-frontend#3073      +/-   ##
==========================================
+ Coverage   95.02%   95.06%   +0.04%     
==========================================
  Files         152      152              
  Lines        2773     2778       +5     
  Branches      541      543       +2     
==========================================
+ Hits         2635     2641       +6     
+ Misses        119      118       -1     
  Partials       19       19
Impacted Files Coverage Δ
src/core/types/addons.js 0% <ø> (ø) ⬆️
src/core/constants.js 100% <ø> (ø) ⬆️
src/core/actions/index.js 100% <ø> (ø) ⬆️
src/disco/sagas/disco.js 100% <100%> (ø) ⬆️
src/core/utils.js 100% <100%> (ø) ⬆️
src/core/reducers/addons.js 100% <100%> (+3.57%) ⬆️
src/core/sagas/addons.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 721f43d...7061c1a. Read the comment docs.

Copy link
Member

@willdurand willdurand left a comment

Choose a reason for hiding this comment

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

I have a few questions.



export const ADDONS_LOADED = 'ADDONS_LOADED';
Copy link
Member

Choose a reason for hiding this comment

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

Can we have LOAD_ADDON instead? See: #3025 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah, right, thanks

name: apiAddon.name,
previews: apiAddon.previews,
public_stats: apiAddon.public_stats,
ratings: apiAddon.ratings || undefined,
Copy link
Member

Choose a reason for hiding this comment

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

Why does this one need 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.

ah, whoops, good catch. That was leftover from me battling with Flow :/

}

export default function addon(
const initialState = {};
Copy link
Member

@willdurand willdurand Sep 7, 2017

Choose a reason for hiding this comment

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

No Flow type here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

return addon.guid;
}

export function removeUndefinedProps(object: Object): Object {
Copy link
Member

Choose a reason for hiding this comment

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

Is this method needed because there are spreads in different places? Otherwise I would argue that the state should have a consistent shape.

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 it is needed for spreads. I added a comment about it below. It's going to be hard to remove the spreads and I think it's a low priority fix.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's a low priority fix.

👍

Copy link
Contributor

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

Wow, this is super-great. It makes the code a lot more readable and easy to grok.

r+wc from me.

type: string,
|};

export function loadEntities(entities: Array<Object>): LoadEntitiesAction {
Copy link
Contributor

Choose a reason for hiding this comment

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

Yay!

type Action = Object;
type AddonState = Object;
export function loadAddons(
entities: {| addons?: ExternalAddonMap |}
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned previously I think it would be great to keep flow definitions out of the function signatures if they're being included. They really crowd the function signature and make it very difficult to parse exactly what's happening inside 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.

The issue I have with making them separate is that it slows down the reader. If you want to know what the type is, you have to cross-reference it from somewhere else. I understand how separation can be helpful for big definitions but this one only spans about 30 characters so I don't think that warrants separation.


// These are custom properties not in the API response.

// TODO: remove this if possible. I think it was added by mistake
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

return apiAddon;

if (apiAddon.current_version && apiAddon.current_version.files.length > 0) {
// TODO: support specific platform files.
Copy link
Contributor

Choose a reason for hiding this comment

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

All these comments are very helpful 🥂!

const { addons } = action.payload;
const newState = { ...state };
Object.keys(addons).forEach((key) => {
newState[key] = createInternalAddon(addons[key]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🎉💃🎉 THANK YOU THIS IS SO MUCH EASIER TO READ 🎉💃🎉

import { fetchAddon as fetchAddonFromApi } from 'core/api';
import { FETCH_ADDON } from 'core/reducers/addons';
import { loadAddons, FETCH_ADDON } from 'core/reducers/addons';
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick but I think we usually load constants first. It technically is alphabetical that way but I guess until we have a rule for sorting imports... 😞

@@ -25,7 +24,7 @@ export function* fetchAddon(
yield put(showLoading());
const state = yield select(getState);
const response = yield call(fetchAddonFromApi, { api: state.api, slug });
yield put(loadEntities(response.entities));
yield put(loadAddons(response.entities));
Copy link
Contributor

Choose a reason for hiding this comment

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

This is just way easier to read too. Thanks a million.

/*
* This is the external API representation of an add-on.
*
* This is a detailed API response. Not all API responses
Copy link
Contributor

Choose a reason for hiding this comment

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

Linking to the API docs from here would be cool just so developers could understand better the varied details in responses. Maybe just http://addons-server.readthedocs.io/en/latest/topics/api/addons.html ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good idea

});

it('sets `isRestartRequired` to `true` when at least one of the files declares it', () => {
it('sets `isRestartRequired` to `true` when some files declare it', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

if the aim here was to shorten this spec I'd say "when any file declares it".

@kumar303
Copy link
Contributor Author

kumar303 commented Sep 7, 2017

Thanks for the reviews! Let's start testing this on dev...

@kumar303 kumar303 merged commit 8489a8e into mozilla:master Sep 7, 2017
@kumar303 kumar303 deleted the addons-reducer-iss3024 branch September 7, 2017 20:50
tsl143 pushed a commit to tsl143/addons-frontend that referenced this pull request Sep 12, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants