-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
48 changed files
with
1,416 additions
and
454 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export { default as {{ name }} } from './{{ name }}'; | ||
export type { {{ getInterface name }} } from './types'; | ||
// above is boilerplate stuff | ||
// replace with your component & props |
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,39 @@ | ||
export const colorState = ['greenLight', 'redLight'] as const; | ||
export type TColorState = typeof colorState[number]; | ||
import { color } from '@web3uikit/styles'; | ||
|
||
export type Colors = keyof typeof color; | ||
|
||
// NOTE: the comment strings are very important | ||
// Storybook pulls them to make our docs | ||
|
||
export interface {{ getInterface name }} { | ||
/** | ||
* Set the Background color of New Component | ||
*/ | ||
bgColor?: Colors; | ||
/** | ||
* The New Component needs text for its green light state | ||
*/ | ||
textOn: string; | ||
|
||
/** | ||
* The New Component needs text for its red light state | ||
*/ | ||
textOff: string; | ||
|
||
/** | ||
* Set the initial state from the New Component | ||
*/ | ||
state?: TColorState; | ||
|
||
/** | ||
* Set the text to have an underline | ||
*/ | ||
hasUnderline?: boolean; | ||
|
||
/** | ||
* The callback function to be called on click | ||
*/ | ||
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; | ||
} |
47 changes: 47 additions & 0 deletions
47
.plop/plop-templates/with-code-examples/{{ name }}.stories.tsx.hbs
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,47 @@ | ||
// importing boilerplate stuff for Storybook | ||
import React from 'react'; | ||
import { ComponentStory, ComponentMeta } from '@storybook/react'; | ||
// importing your new component | ||
import {{ name }} from './{{ name }}'; | ||
|
||
// title: group / name in Storybook | ||
// component: your new component | ||
// argTypes: onClick is a 'Storybook Event' to simulate clicks | ||
export default { | ||
title: '{{ category }}/{{ name }}', | ||
component: {{ name }}, | ||
argTypes: { onClick: { action: 'clicked' } }, | ||
} as ComponentMeta<typeof {{ name }}>; | ||
|
||
// another boilerplate to set up your Storybook template with your new component | ||
const Template: ComponentStory<typeof {{ name }}> = (args) => ( | ||
<{{ name }} {...args} /> | ||
); | ||
|
||
////////////////////////////////////////////////////////////////////////////// | ||
// NOTE please only include the min props needed for each render | ||
// this means the next dev using 'get code' in Storybook will not get confused | ||
////////////////////////////////////////////////////////////////////////////// | ||
|
||
// Story 1 Default | ||
export const Default = Template.bind({}); | ||
Default.args = { | ||
textOn: 'green light', | ||
textOff: 'red light!', | ||
}; | ||
|
||
// Story 2 InitializeRed | ||
export const InitializeRed = Template.bind({}); | ||
InitializeRed.args = { | ||
textOn: 'green light', | ||
textOff: 'red light!', | ||
state: 'redLight', | ||
}; | ||
|
||
// Story 3 UnderLinedText | ||
export const UnderLinedText = Template.bind({}); | ||
UnderLinedText.args = { | ||
textOn: 'green light', | ||
textOff: 'red light!', | ||
hasUnderline: true, | ||
}; |
84 changes: 84 additions & 0 deletions
84
.plop/plop-templates/with-code-examples/{{ name }}.styles.ts.hbs
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,84 @@ | ||
// importing styled to make components and css to make themes | ||
import styled, { css } from 'styled-components'; | ||
|
||
// importing centralized styles | ||
import {color, fonts, resetCSS} from '@web3uikit/styles'; | ||
|
||
// import our types to conditionally render CSS | ||
import type { {{ getInterface name }} } from './types'; | ||
|
||
// pick the props that you will use for conditional CSS | ||
type TStyleProps = Pick<{{ getInterface name }}, 'state' | 'hasUnderline' | 'bgColor'>; | ||
|
||
// ////////////////// | ||
// Theme CSS | ||
// CSS Props should be sorted alphabetically | ||
// ////////////////// | ||
const greenColor = css` | ||
color: ${color.green}; | ||
`; | ||
const redColor = css` | ||
color: ${color.red}; | ||
`; | ||
|
||
// ////////////////// | ||
// Styled Components | ||
// CSS Props should be sorted alphabetically | ||
// ////////////////// | ||
const SectionStyled = styled.section<TStyleProps>` | ||
border-bottom: 5px solid ${color.green}; | ||
border-top: 5px solid ${color.yellow}; | ||
padding: 12px 24px; | ||
background-color: ${(p) => p.bgColor && color[p.bgColor]}; | ||
`; | ||
|
||
const SpanStyled = styled.span` | ||
display: flex; | ||
align-items: center; | ||
|
||
svg { | ||
margin-right: 8px; | ||
} | ||
`; | ||
|
||
const TitleStyled = styled.h1<TStyleProps>` | ||
${resetCSS}; | ||
${fonts.heading}; | ||
${fonts.h1}; | ||
margin-bottom: 12px; | ||
`; | ||
|
||
const HeadingStyled = styled.h2<TStyleProps>` | ||
${resetCSS}; | ||
${fonts.heading}; | ||
${fonts.h2}; | ||
margin-bottom: 12px; | ||
${(p) => (p.state === 'greenLight' ? greenColor : redColor)}; | ||
`; | ||
|
||
const TextStyled = styled.p<TStyleProps>` | ||
${resetCSS}; | ||
${fonts.heading}; | ||
${fonts.text}; | ||
margin-top: 12px; | ||
text-decoration: ${(p) => (p.hasUnderline ? 'underline' : 'none')}; ; | ||
`; | ||
|
||
// CSS ORDERING | ||
// 1 - Imported styles (font, colors, etc) | ||
// 2 - Normal styles (margin, padding, etc) | ||
// 3 - Child elements (span, svg, etc) | ||
// 4 - Pseudo elements (before & after) | ||
// 5 - Modifier styles (hover, active etc) | ||
// 6 - State changed styles ${(p) => (p.prop ? green : red)}; | ||
// each should be sorted alphabetically as best as possible | ||
|
||
export default { | ||
HeadingStyled, | ||
SectionStyled, | ||
SpanStyled, | ||
TextStyled, | ||
TitleStyled, | ||
greenColor, | ||
redColor, | ||
}; |
202 changes: 202 additions & 0 deletions
202
.plop/plop-templates/with-code-examples/{{ name }}.test.tsx.hbs
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,202 @@ | ||
// importing boilerplate stuff | ||
import React from 'react'; | ||
import { composeStories } from '@storybook/testing-react'; | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import * as stories from './{{ name }}.stories'; | ||
|
||
// // importing fire event from RTL to mock a click event | ||
// import { fireEvent } from '@testing-library/react'; | ||
|
||
// importing color and a testing tool to convert RGB to HEX | ||
import {color,rgbToHex} from '@web3uikit/styles'; | ||
|
||
// importing testID from button and icon | ||
import { buttonTestId } from '../Button/Button.test'; | ||
|
||
const iconTestId = 'test-icon'; | ||
|
||
// importing my stories to test | ||
const { Default, InitializeRed, UnderLinedText } = composeStories(stories); | ||
|
||
// setting my test IDs to match my tsx | ||
export const testCompId = 'test-new-comp'; | ||
const testTitle = 'test-title'; | ||
const testHeading = 'test-heading'; | ||
const testText = 'test-text'; | ||
// NOTE: the main test ID is exported incase | ||
// it is needed for another components test | ||
|
||
// ///////////////////////////////////////////////////// | ||
// examples of basic tests of props, values and styles | ||
// ///////////////////////////////////////////////////// | ||
|
||
// Test Story 1: Default | ||
test('Renders Default component', () => { | ||
const testTextOn = Default?.args?.textOn; | ||
|
||
render(<Default />); | ||
|
||
const component = screen.getByTestId(testCompId); | ||
expect(component).not.toBeNull(); | ||
|
||
const icon = screen.getByTestId(iconTestId); | ||
expect(icon).not.toBeNull(); | ||
|
||
const title = screen.getByTestId(testTitle); | ||
expect(title).not.toBeNull(); | ||
expect(title.textContent).toBe('The Demo Component'); | ||
|
||
const heading = screen.getByTestId(testHeading); | ||
expect(heading).not.toBeNull(); | ||
expect(heading.textContent).toBe(testTextOn); | ||
|
||
const styles = heading && getComputedStyle(heading); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.green); | ||
|
||
const text = screen.getByTestId(testText); | ||
expect(text).not.toBeNull(); | ||
expect(text.textContent).toBe('Clicked: 0 times'); | ||
|
||
const textWithoutUnderline = screen.getByTestId(testText); | ||
expect(textWithoutUnderline).not.toBeNull(); | ||
const twlStyles = | ||
textWithoutUnderline && getComputedStyle(textWithoutUnderline); | ||
expect(twlStyles?.textDecoration).toBe('none'); | ||
}); | ||
|
||
// Test Story 2: Button Click | ||
test('changes UI onClick of the button', () => { | ||
const testTextOff = Default?.args?.textOff; | ||
|
||
render(<Default />); | ||
|
||
const buttonElement = screen.getByTestId(buttonTestId); | ||
|
||
buttonElement && fireEvent.click(buttonElement); | ||
|
||
const textElelement = screen.getByTestId(testText); | ||
expect(textElelement).not.toBeNull(); | ||
expect(textElelement.textContent).toBe('Clicked: 1 times'); | ||
|
||
const headingElement = screen.getByTestId(testHeading); | ||
expect(headingElement).not.toBeNull(); | ||
expect(headingElement.textContent).toBe(testTextOff); | ||
|
||
const styles = headingElement && getComputedStyle(headingElement); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.red); | ||
}); | ||
|
||
// Test Story 3: InitializeRed | ||
test('Renders InitializeRed', () => { | ||
const testTextOff = InitializeRed?.args?.textOff; | ||
|
||
render(<InitializeRed />); | ||
|
||
const component = screen.getByTestId(testCompId); | ||
expect(component).not.toBeNull(); | ||
|
||
const icon = screen.getByTestId(iconTestId); | ||
expect(icon).not.toBeNull(); | ||
|
||
const title = screen.getByTestId(testTitle); | ||
expect(title).not.toBeNull(); | ||
expect(title.textContent).toBe('The Demo Component'); | ||
|
||
const heading = screen.getByTestId(testHeading); | ||
expect(heading).not.toBeNull(); | ||
expect(heading.textContent).toBe(testTextOff); | ||
|
||
const styles = heading && getComputedStyle(heading); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.red); | ||
|
||
const text = screen.getByTestId(testText); | ||
expect(text).not.toBeNull(); | ||
expect(text.textContent).toBe('Clicked: 0 times'); | ||
|
||
const textWithoutUnderline = screen.getByTestId(testText); | ||
expect(textWithoutUnderline).not.toBeNull(); | ||
const twlStyles = | ||
textWithoutUnderline && getComputedStyle(textWithoutUnderline); | ||
expect(twlStyles?.textDecoration).toBe('none'); | ||
}); | ||
|
||
// Test Story 3: Button click | ||
test('changes UI onClick of the button', () => { | ||
const testTextOn = InitializeRed?.args?.textOn; | ||
|
||
render(<InitializeRed />); | ||
|
||
const buttonElement = screen.getByTestId(buttonTestId); | ||
buttonElement && fireEvent.click(buttonElement); | ||
|
||
const textElelement = screen.getByTestId(testText); | ||
expect(textElelement).not.toBeNull(); | ||
expect(textElelement.textContent).toBe('Clicked: 1 times'); | ||
|
||
const headingElement = screen.getByTestId(testHeading); | ||
expect(headingElement).not.toBeNull(); | ||
expect(headingElement.textContent).toBe(testTextOn); | ||
|
||
const styles = headingElement && getComputedStyle(headingElement); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.green); | ||
}); | ||
|
||
// Test Story 4: UnderLinedText | ||
test('Renders UnderLinedText', () => { | ||
const testTextOn = UnderLinedText?.args?.textOn; | ||
|
||
render(<UnderLinedText />); | ||
|
||
const component = screen.getByTestId(testCompId); | ||
expect(component).not.toBeNull(); | ||
|
||
const icon = screen.getByTestId(iconTestId); | ||
expect(icon).not.toBeNull(); | ||
|
||
const title = screen.getByTestId(testTitle); | ||
expect(title).not.toBeNull(); | ||
expect(title.textContent).toBe('The Demo Component'); | ||
|
||
const heading = screen.getByTestId(testHeading); | ||
expect(heading).not.toBeNull(); | ||
expect(heading.textContent).toBe(testTextOn); | ||
|
||
const styles = heading && getComputedStyle(heading); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.green); | ||
|
||
const text = screen.getByTestId(testText); | ||
expect(text).not.toBeNull(); | ||
expect(text.textContent).toBe('Clicked: 0 times'); | ||
|
||
const textWithoutUnderline = screen.queryByTestId(testText); | ||
expect(textWithoutUnderline).not.toBeNull(); | ||
const twlStyles = | ||
textWithoutUnderline && getComputedStyle(textWithoutUnderline); | ||
expect(twlStyles?.textDecoration).toBe('underline'); | ||
}); | ||
|
||
test('changes UI onClick of the button', () => { | ||
const testTextOff = UnderLinedText?.args?.textOff; | ||
|
||
render(<UnderLinedText />); | ||
|
||
const buttonElement = screen.getByTestId(buttonTestId); | ||
buttonElement && fireEvent.click(buttonElement); | ||
|
||
const textElelement = screen.getByTestId(testText); | ||
expect(textElelement).not.toBeNull(); | ||
expect(textElelement.textContent).toBe('Clicked: 1 times'); | ||
|
||
const headingElement = screen.getByTestId(testHeading); | ||
expect(headingElement).not.toBeNull(); | ||
expect(headingElement.textContent).toBe(testTextOff); | ||
|
||
const styles = headingElement && getComputedStyle(headingElement); | ||
const colorHex = styles && rgbToHex(styles.color).toUpperCase(); | ||
expect(colorHex).toBe(color.red); | ||
}); |
Oops, something went wrong.