Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Storybook and TS migration of ErrorPlaceholder component #5294

Merged
merged 3 commits into from
Dec 2, 2021

Conversation

sunyatasattva
Copy link
Contributor

This PR adds stories for the ErrorPlaceholder component and migrates it to TypeScript.

Fixes #5255

Testing

Manual Testing

How to test the changes in this Pull Request:

  1. Run npm run storybook

  2. Explore the Errors stories. You should see five stories:

    • A base one with just the error message
    • The default placeholder with a generic error
    • Variation with an API type error
    • Variation with unknown error
    • Variation without retry button

In all the variations with the retry button, you should be able to click it and it will simulate a loading event for 3.5s.

User Facing Testing

These are steps for user testing (where "user" is someone interacting with this change that is not editing any code).

  • Same as above

Stories include:

* Default generic error
* API error
* Unknown error
* Error without possibility to retry
* Base Error atom

Where applicable, the **Retry** button will not only trigger the appropriate
action, but also simulate the loading state of the error component.
@sunyatasattva sunyatasattva added focus: components Work that introduces new or updates existing components. type: refactor The issue/PR is related to refactoring. skip-changelog PRs that you don't want to appear in the changelog. type: task The issue is an internally driven task (e.g. from another A8c team). type: technical debt This issue/PR represents/solves the technical debt of the project. labels Dec 1, 2021
@sunyatasattva sunyatasattva self-assigned this Dec 1, 2021
@rubikuserbot rubikuserbot requested review from a team and gigitux and removed request for a team December 1, 2021 17:01
@github-actions
Copy link
Contributor

github-actions bot commented Dec 1, 2021

Size Change: -8 B (0%)

Total Size: 1.04 MB

Filename Size Change
build/all-products.js 32.9 kB -3 B (0%)
build/all-reviews.js 8.31 kB +2 B (0%)
build/featured-category.js 6.67 kB -4 B (0%)
build/featured-product.js 8.02 kB -2 B (0%)
build/handpicked-products.js 5.37 kB -1 B (0%)
build/product-best-sellers.js 5.57 kB +1 B (0%)
build/product-new.js 5.73 kB +1 B (0%)
build/product-top-rated.js 5.7 kB +1 B (0%)
build/products-by-attribute.js 6.61 kB -1 B (0%)
build/reviews-by-category.js 9.96 kB +2 B (0%)
build/reviews-by-product.js 11 kB +1 B (0%)
build/single-product.js 8.5 kB -5 B (0%)
ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 6.23 kB
build/active-filters.js 7.09 kB
build/all-products-frontend.js 22.1 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button--atomic-block-components/image---a7e2bb9b.js 2.77 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 1.49 kB
build/atomic-block-components/add-to-cart-frontend.js 6.87 kB
build/atomic-block-components/add-to-cart.js 6.44 kB
build/atomic-block-components/button-frontend.js 1.48 kB
build/atomic-block-components/button.js 851 B
build/atomic-block-components/category-list-frontend.js 457 B
build/atomic-block-components/category-list.js 457 B
build/atomic-block-components/image-frontend.js 1.38 kB
build/atomic-block-components/image.js 1.05 kB
build/atomic-block-components/price-frontend.js 1.74 kB
build/atomic-block-components/price.js 1.69 kB
build/atomic-block-components/rating-frontend.js 553 B
build/atomic-block-components/rating.js 554 B
build/atomic-block-components/sale-badge-frontend.js 626 B
build/atomic-block-components/sale-badge.js 624 B
build/atomic-block-components/sku-frontend.js 385 B
build/atomic-block-components/sku.js 385 B
build/atomic-block-components/stock-indicator-frontend.js 583 B
build/atomic-block-components/stock-indicator.js 586 B
build/atomic-block-components/summary-frontend.js 874 B
build/atomic-block-components/summary.js 874 B
build/atomic-block-components/tag-list-frontend.js 458 B
build/atomic-block-components/tag-list.js 457 B
build/atomic-block-components/title-frontend.js 1.11 kB
build/atomic-block-components/title.js 1.11 kB
build/attribute-filter-frontend.js 16.6 kB
build/attribute-filter.js 10.8 kB
build/blocks-checkout.js 20.8 kB
build/cart-blocks/accepted-payment-methods-frontend.js 1.14 kB
build/cart-blocks/checkout-button-frontend.js 1.14 kB
build/cart-blocks/empty-cart-frontend.js 346 B
build/cart-blocks/express-payment-frontend.js 4.82 kB
build/cart-blocks/filled-cart-frontend.js 768 B
build/cart-blocks/items-frontend.js 298 B
build/cart-blocks/line-items-frontend.js 5.12 kB
build/cart-blocks/order-summary-frontend.js 8.95 kB
build/cart-blocks/totals-frontend.js 320 B
build/cart-frontend.js 49.1 kB
build/cart.js 44.8 kB
build/checkout-blocks/actions-frontend.js 1.44 kB
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.24 kB
build/checkout-blocks/billing-address-frontend.js 890 B
build/checkout-blocks/contact-information-frontend.js 2.94 kB
build/checkout-blocks/express-payment-frontend.js 5.11 kB
build/checkout-blocks/fields-frontend.js 343 B
build/checkout-blocks/order-note-frontend.js 1.13 kB
build/checkout-blocks/order-summary-frontend.js 11.4 kB
build/checkout-blocks/payment-frontend.js 7.49 kB
build/checkout-blocks/shipping-address-frontend.js 976 B
build/checkout-blocks/shipping-methods-frontend.js 4.89 kB
build/checkout-blocks/terms-frontend.js 1.22 kB
build/checkout-blocks/totals-frontend.js 323 B
build/checkout-frontend.js 51.3 kB
build/checkout.js 47.9 kB
build/legacy-template.js 2.05 kB
build/mini-cart-component-frontend.js 40.9 kB
build/mini-cart-contents.js 1.81 kB
build/mini-cart-frontend.js 1.74 kB
build/mini-cart.js 6.23 kB
build/price-filter-frontend.js 12.4 kB
build/price-filter.js 8.62 kB
build/price-format.js 1.19 kB
build/product-categories.js 3.46 kB
build/product-category.js 6.44 kB
build/product-on-sale.js 6.11 kB
build/product-search.js 2.47 kB
build/product-tag.js 5.81 kB
build/reviews-frontend.js 7.21 kB
build/single-product-frontend.js 25.5 kB
build/stock-filter-frontend.js 6.81 kB
build/stock-filter.js 6.81 kB
build/vendors--atomic-block-components/add-to-cart--cart-blocks/order-summary--checkout-blocks/billing-ad--c5eb4dcd-frontend.js 16.1 kB
build/vendors--atomic-block-components/add-to-cart-frontend.js 4.45 kB
build/vendors--atomic-block-components/price--cart-blocks/line-items--cart-blocks/order-summary--checkout--8a3571de-frontend.js 5.71 kB
build/vendors--cart-blocks/line-items--checkout-blocks/order-summary-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/order-summary---eb4d2cec-frontend.js 5.02 kB
build/wc-blocks-data.js 8.84 kB
build/wc-blocks-editor-style-rtl.css 15.8 kB
build/wc-blocks-editor-style.css 15.8 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 949 B
build/wc-blocks-registry.js 2.69 kB
build/wc-blocks-shared-context.js 1.51 kB
build/wc-blocks-shared-hocs.js 1.14 kB
build/wc-blocks-style-rtl.css 21.1 kB
build/wc-blocks-style.css 21.1 kB
build/wc-blocks-vendors-style-rtl.css 1.37 kB
build/wc-blocks-vendors-style.css 1.37 kB
build/wc-blocks-vendors.js 254 kB
build/wc-blocks.js 2.96 kB
build/wc-payment-method-bacs.js 820 B
build/wc-payment-method-cheque.js 816 B
build/wc-payment-method-cod.js 912 B
build/wc-payment-method-paypal.js 838 B
build/wc-payment-method-stripe.js 11.1 kB
build/wc-settings.js 2.58 kB

compressed-size-action

Copy link
Contributor

@gigitux gigitux left a comment

Choose a reason for hiding this comment

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

LGTM! 🚢

Just a comment about the String Literal Type.
In any case, I'm approving this 👍

/**
* Context in which the error was triggered. That will determine how the error is displayed to the user.
*/
type: 'api' | 'general';
Copy link
Contributor

Choose a reason for hiding this comment

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

In these cases, I prefer to use an enum. This will allow for easy refactor in the future if there should be a need

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While I am also a fan of enums, I feel there are different use-cases which fits best each type, and one shouldn't default to enums, in general. Here is a quick rundown: https://blog.bam.tech/developer-news/should-you-use-enums-or-union-types-in-typescript and here also a nice SO opinion: https://stackoverflow.com/a/60041791/313115

In general, for example, enums are great for readability when their key is not equivalent to their value. Imagine something like:

{
  keycode: 37 | 38 | 39 | 40
}

This doesn't give the reader much information on what's going on. Rather:

enum Keycode {
  ARROW_LEFT = 37,
  ARROW_UP = 38,
  ARROW_RIGHT = 39,
  ARROW_DOWN = 40
}

// ...

{
  keycode: Keycode
}

The above is much more terse. In our case, the enum would be something like:

enum ErrorType {
  API = 'api'
  GENERAL = 'general'
}

I wouldn't say that's very helpful on the readability. I understand what you are saying regarding refactoring, but the SO answer above mentions iterating through a const, which I think it fits our case better. Something like:

const errorTypes = [ 'api', 'general' ] as const;
type ErrorTypes = typeof errorTypes[number];

Anyways, in this case, as we have only two types, I think this is slight premature optimization, so my opinion here is YAGNI.

But that's just my 2c, curious to hear what do you think. 🙏

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for sending me these resources!
About readability you can define an enum like this:

enum Error = {
API,
GENERAL
}

For me, the advantage of enums (and the killer feature too) is that we can easily rename for the entire project, instead of the string literal.

Anyways, in this case, as we have only two types, I think this is slight premature optimization, so my opinion here is YAGNI.

I agree, but potentially this component it's a "global" component, so it is better to think about it now that refactor later

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For me, the advantage of enums (and the killer feature too) is that we can easily rename for the entire project, instead of the string literal.

Mm, I see what you mean! However you could do the same renaming globally by just extracting the union type. There is no advantage in terms of refactoring between doing:

enum ErrorType = {
  API,
  GENERAL
}

and

type ErrorType = 'api' | 'general';

As long as you export both of those things and import them, refactoring is going to involve the exact amount of work. So I'm not sure if that's a significant advantage.

With that said, obviously, in this specific case it is actually a “hard-coded” string union type, so for refactoring reasons, definitely it might be better to extract it into its own type.

As a matter of fact, if you see the code changes, that's an approach I took elsewhere. Previously the code had:

error: PropTypes.shape( {
		/**
		 * Human-readable error message to display.
		 */
		message: PropTypes.node,
		/**
		 * Context in which the error was triggered. That will determine how the error is displayed to the user.
		 */
		type: PropTypes.oneOf( [ 'api', 'general' ] ),
	} )

The above was already repeated twice, so I refactored it in its own type. Some go by the Rule of Three when refactoring, though I am a bit more extreme and I usually refactor earlier (some say to a fault). But I definitely agree with you there about long term thinking and also, again, I am a fan of using Enums! 🤓

@github-actions github-actions bot modified the milestone: 6.5.0 Dec 2, 2021
@sunyatasattva sunyatasattva merged commit af6b466 into trunk Dec 2, 2021
@sunyatasattva sunyatasattva deleted the fix/5255-storybook-errorplaceholder branch December 2, 2021 16:56
jonny-bull pushed a commit to jonny-bull/woocommerce-gutenberg-products-block that referenced this pull request Dec 14, 2021
…ce#5294)

* Convert `ErrorPlaceholder` and `ErrorMessage` to TypeScript

* Add stories for `ErrorPlaceholder` and `ErrorMessage` (woocommerce#5255)

Stories include:

* Default generic error
* API error
* Unknown error
* Error without possibility to retry
* Base Error atom

Where applicable, the **Retry** button will not only trigger the appropriate
action, but also simulate the loading state of the error component.

* Update references to `ErrorMessage` component to leave the file extension out

Fix woocommerce#5255
Refs woocommerce#5249
jonny-bull pushed a commit to jonny-bull/woocommerce-gutenberg-products-block that referenced this pull request Dec 16, 2021
…ce#5294)

* Convert `ErrorPlaceholder` and `ErrorMessage` to TypeScript

* Add stories for `ErrorPlaceholder` and `ErrorMessage` (woocommerce#5255)

Stories include:

* Default generic error
* API error
* Unknown error
* Error without possibility to retry
* Base Error atom

Where applicable, the **Retry** button will not only trigger the appropriate
action, but also simulate the loading state of the error component.

* Update references to `ErrorMessage` component to leave the file extension out

Fix woocommerce#5255
Refs woocommerce#5249
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
focus: components Work that introduces new or updates existing components. skip-changelog PRs that you don't want to appear in the changelog. type: refactor The issue/PR is related to refactoring. type: task The issue is an internally driven task (e.g. from another A8c team). type: technical debt This issue/PR represents/solves the technical debt of the project.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Revise storybook entry for ErrorPlaceholder component
2 participants