Skip to content

Commit

Permalink
chore: integrate plop and bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
AbhinavMV committed Jun 18, 2022
1 parent a5080d0 commit ae21889
Show file tree
Hide file tree
Showing 48 changed files with 1,416 additions and 454 deletions.
4 changes: 4 additions & 0 deletions .plop/plop-templates/with-code-examples/index.tsx.hbs
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
39 changes: 39 additions & 0 deletions .plop/plop-templates/with-code-examples/types.ts.hbs
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 .plop/plop-templates/with-code-examples/{{ name }}.stories.tsx.hbs
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 .plop/plop-templates/with-code-examples/{{ name }}.styles.ts.hbs
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 .plop/plop-templates/with-code-examples/{{ name }}.test.tsx.hbs
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);
});
Loading

0 comments on commit ae21889

Please sign in to comment.