├── .gitattributes
├── 9781484266953.jpg
├── Ch1
├── .DS_Store
├── TS-getting-started.ts
└── index.html
├── Ch10
├── .DS_Store
└── e2e_ts_testing_with_puppeteer
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ └── README
│ ├── components
│ │ └── README
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ └── README
│ ├── pages
│ │ └── README
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ └── README
│ │ └── selectors
│ │ │ └── README
│ ├── redux
│ │ └── store.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
│ └── tsconfig.json
├── Ch12
├── .env
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .prettierrc
├── README.md
├── README_CRA.md
├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
├── generate-react-cli.json
├── jest-puppeteer.config.js
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ └── README
│ ├── components
│ │ ├── README
│ │ └── ScrollToTop
│ │ │ └── ScrollToTop.tsx
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ └── README
│ ├── pages
│ │ ├── MyPage
│ │ │ ├── MyPage.scss
│ │ │ ├── MyPage.test.tsx
│ │ │ ├── MyPage.tsx
│ │ │ └── math.tsx
│ │ └── README
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ └── README
│ │ └── selectors
│ │ │ └── README
│ ├── redux
│ │ └── store.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
└── tsconfig.json
├── Ch2
├── .DS_Store
├── hello-cra
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── starter-project
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .prettierrc
│ ├── generate-react-cli.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── App.css
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── logo.svg
│ ├── react-app-env.d.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ └── component
│ │ ├── component.js
│ │ ├── style.scss
│ │ └── test.js
│ ├── tsconfig.json
│ └── yarn.lock
├── Ch3
├── .DS_Store
└── WelcomeUser.html
├── Ch4
├── .DS_Store
├── exercise-4-1
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ │ ├── app.test.tsx
│ │ ├── global.d.ts
│ │ ├── jest.config.js
│ │ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── .DS_Store
│ │ ├── App.scss
│ │ ├── App.test.tsx
│ │ ├── App.tsx
│ │ ├── AppRouter.test.tsx
│ │ ├── AppRouter.tsx
│ │ ├── assets
│ │ │ └── README
│ │ ├── components
│ │ │ └── README
│ │ ├── features
│ │ │ └── README
│ │ ├── index.scss
│ │ ├── index.tsx
│ │ ├── layout
│ │ │ ├── Footer
│ │ │ │ ├── Footer.scss
│ │ │ │ ├── Footer.test.tsx
│ │ │ │ └── Footer.tsx
│ │ │ ├── Header
│ │ │ │ ├── Header.scss
│ │ │ │ ├── Header.test.tsx
│ │ │ │ └── Header.tsx
│ │ │ └── README
│ │ ├── logo.svg
│ │ ├── model
│ │ │ └── README
│ │ ├── pages
│ │ │ ├── ArticlesPage
│ │ │ │ ├── ArticlesPage.scss
│ │ │ │ ├── ArticlesPage.test.tsx
│ │ │ │ └── ArticlesPage.tsx
│ │ │ ├── BooksPage
│ │ │ │ ├── BooksPage.scss
│ │ │ │ ├── BooksPage.test.tsx
│ │ │ │ └── BooksPage.tsx
│ │ │ ├── BuildSiteCoursePage
│ │ │ │ ├── BuildSiteCoursePage.scss
│ │ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ │ └── BuildSiteCoursePage.tsx
│ │ │ ├── CoachingHourlyPage
│ │ │ │ ├── CoachingHourlyPage.scss
│ │ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ │ └── CoachingHourlyPage.tsx
│ │ │ ├── CoachingPackagePage
│ │ │ │ ├── CoachingPackagePage.scss
│ │ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ │ └── CoachingPackagePage.tsx
│ │ │ ├── ContactPage
│ │ │ │ ├── ContactPage.scss
│ │ │ │ ├── ContactPage.test.tsx
│ │ │ │ └── ContactPage.tsx
│ │ │ ├── HomePage
│ │ │ │ ├── HomePage.scss
│ │ │ │ ├── HomePage.test.tsx
│ │ │ │ └── HomePage.tsx
│ │ │ ├── LoginPage
│ │ │ │ ├── LoginPage.scss
│ │ │ │ ├── LoginPage.test.tsx
│ │ │ │ └── LoginPage.tsx
│ │ │ ├── MembersPage
│ │ │ │ ├── MembersPage.scss
│ │ │ │ ├── MembersPage.test.tsx
│ │ │ │ └── MembersPage.tsx
│ │ │ ├── NotFoundPage
│ │ │ │ ├── NotFoundPage.scss
│ │ │ │ ├── NotFoundPage.test.tsx
│ │ │ │ └── NotFoundPage.tsx
│ │ │ ├── README
│ │ │ └── YouBuildMySitePage
│ │ │ │ ├── YouBuildMySitePage.scss
│ │ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ │ └── YouBuildMySitePage.tsx
│ │ ├── react-app-env.d.ts
│ │ ├── recoil
│ │ │ ├── atoms
│ │ │ │ └── README
│ │ │ └── selectors
│ │ │ │ └── README
│ │ ├── redux
│ │ │ └── store.ts
│ │ ├── serviceWorker.ts
│ │ └── setupTests.ts
│ ├── templates
│ │ ├── component
│ │ │ ├── component.js
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ ├── test.js
│ │ │ └── test.tsx
│ │ └── page
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
└── exercise-4-2
│ ├── .DS_Store
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── .DS_Store
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ └── README
│ ├── components
│ │ └── README
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ ├── Footer
│ │ │ ├── Footer.scss
│ │ │ ├── Footer.test.tsx
│ │ │ └── Footer.tsx
│ │ ├── Header
│ │ │ ├── Header.scss
│ │ │ ├── Header.test.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── HeaderDrawer.tsx
│ │ │ ├── HeaderTheme.tsx
│ │ │ └── HeaderTopNav.tsx
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ └── README
│ ├── pages
│ │ ├── ArticlesPage
│ │ │ ├── ArticlesPage.scss
│ │ │ ├── ArticlesPage.test.tsx
│ │ │ └── ArticlesPage.tsx
│ │ ├── BooksPage
│ │ │ ├── BooksPage.scss
│ │ │ ├── BooksPage.test.tsx
│ │ │ └── BooksPage.tsx
│ │ ├── BuildSiteCoursePage
│ │ │ ├── BuildSiteCoursePage.scss
│ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ └── BuildSiteCoursePage.tsx
│ │ ├── CoachingHourlyPage
│ │ │ ├── CoachingHourlyPage.scss
│ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ └── CoachingHourlyPage.tsx
│ │ ├── CoachingPackagePage
│ │ │ ├── CoachingPackagePage.scss
│ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ └── CoachingPackagePage.tsx
│ │ ├── ContactPage
│ │ │ ├── ContactPage.scss
│ │ │ ├── ContactPage.test.tsx
│ │ │ └── ContactPage.tsx
│ │ ├── HomePage
│ │ │ ├── HomePage.scss
│ │ │ ├── HomePage.test.tsx
│ │ │ └── HomePage.tsx
│ │ ├── LoginPage
│ │ │ ├── LoginPage.scss
│ │ │ ├── LoginPage.test.tsx
│ │ │ └── LoginPage.tsx
│ │ ├── MembersPage
│ │ │ ├── MembersPage.scss
│ │ │ ├── MembersPage.test.tsx
│ │ │ └── MembersPage.tsx
│ │ ├── NotFoundPage
│ │ │ ├── NotFoundPage.scss
│ │ │ ├── NotFoundPage.test.tsx
│ │ │ └── NotFoundPage.tsx
│ │ ├── README
│ │ └── YouBuildMySitePage
│ │ │ ├── YouBuildMySitePage.scss
│ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ └── YouBuildMySitePage.tsx
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ └── README
│ │ └── selectors
│ │ │ └── README
│ ├── redux
│ │ └── store.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
├── Ch5
├── .DS_Store
├── README.md
├── README_CRA.md
├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
├── generate-react-cli.json
├── jest-puppeteer.config.js
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── .DS_Store
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.scss
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ └── README
│ ├── components
│ │ └── README
│ ├── features
│ │ ├── Preferences
│ │ │ └── preferencesSlice.ts
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ ├── Footer
│ │ │ ├── Footer.scss
│ │ │ ├── Footer.styles.ts
│ │ │ ├── Footer.test.tsx
│ │ │ ├── Footer.tsx
│ │ │ └── FooterTheme.tsx
│ │ ├── Header
│ │ │ ├── Header.scss
│ │ │ ├── Header.test.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── HeaderDrawer.tsx
│ │ │ ├── HeaderTheme.tsx
│ │ │ └── HeaderTopNav.tsx
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ ├── README
│ │ ├── index.ts
│ │ └── preferencesObject.ts
│ ├── pages
│ │ ├── ArticlesPage
│ │ │ ├── ArticlesPage.scss
│ │ │ ├── ArticlesPage.test.tsx
│ │ │ └── ArticlesPage.tsx
│ │ ├── BooksPage
│ │ │ ├── BooksPage.scss
│ │ │ ├── BooksPage.test.tsx
│ │ │ └── BooksPage.tsx
│ │ ├── BuildSiteCoursePage
│ │ │ ├── BuildSiteCoursePage.scss
│ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ └── BuildSiteCoursePage.tsx
│ │ ├── CoachingHourlyPage
│ │ │ ├── CoachingHourlyPage.scss
│ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ └── CoachingHourlyPage.tsx
│ │ ├── CoachingPackagePage
│ │ │ ├── CoachingPackagePage.scss
│ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ └── CoachingPackagePage.tsx
│ │ ├── ContactPage
│ │ │ ├── ContactPage.scss
│ │ │ ├── ContactPage.test.tsx
│ │ │ └── ContactPage.tsx
│ │ ├── HomePage
│ │ │ ├── HomePage.scss
│ │ │ ├── HomePage.test.tsx
│ │ │ └── HomePage.tsx
│ │ ├── LoginPage
│ │ │ ├── LoginPage.scss
│ │ │ ├── LoginPage.test.tsx
│ │ │ └── LoginPage.tsx
│ │ ├── MembersPage
│ │ │ ├── MembersPage.scss
│ │ │ ├── MembersPage.test.tsx
│ │ │ └── MembersPage.tsx
│ │ ├── NotFoundPage
│ │ │ ├── NotFoundPage.scss
│ │ │ ├── NotFoundPage.test.tsx
│ │ │ └── NotFoundPage.tsx
│ │ ├── README
│ │ └── YouBuildMySitePage
│ │ │ ├── YouBuildMySitePage.scss
│ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ └── YouBuildMySitePage.tsx
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ └── README
│ │ └── selectors
│ │ │ └── README
│ ├── redux
│ │ └── store.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
├── tsconfig.json
└── yarn.lock
├── Ch6
├── exercise-6-1
│ ├── .DS_Store
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ │ ├── app.test.tsx
│ │ ├── global.d.ts
│ │ ├── jest.config.js
│ │ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── .DS_Store
│ │ ├── App.scss
│ │ ├── App.test.tsx
│ │ ├── App.tsx
│ │ ├── AppRouter.scss
│ │ ├── AppRouter.test.tsx
│ │ ├── AppRouter.tsx
│ │ ├── assets
│ │ │ └── README
│ │ ├── components
│ │ │ ├── README
│ │ │ ├── UserButton
│ │ │ │ ├── UserButton.scss
│ │ │ │ └── UserButton.tsx
│ │ │ └── UserListButton
│ │ │ │ └── UserListButton.tsx
│ │ ├── features
│ │ │ └── README
│ │ ├── index.scss
│ │ ├── index.tsx
│ │ ├── layout
│ │ │ ├── Footer
│ │ │ │ ├── Footer.scss
│ │ │ │ ├── Footer.styles.ts
│ │ │ │ ├── Footer.test.tsx
│ │ │ │ ├── Footer.tsx
│ │ │ │ └── FooterTheme.tsx
│ │ │ ├── Header
│ │ │ │ ├── Header.scss
│ │ │ │ ├── Header.test.tsx
│ │ │ │ ├── Header.tsx
│ │ │ │ ├── HeaderDrawer.tsx
│ │ │ │ ├── HeaderTheme.tsx
│ │ │ │ └── HeaderTopNav.tsx
│ │ │ └── README
│ │ ├── logo.svg
│ │ ├── model
│ │ │ ├── README
│ │ │ ├── index.ts
│ │ │ └── preferencesObject.ts
│ │ ├── pages
│ │ │ ├── ArticlesPage
│ │ │ │ ├── ArticlesPage.scss
│ │ │ │ ├── ArticlesPage.test.tsx
│ │ │ │ └── ArticlesPage.tsx
│ │ │ ├── BooksPage
│ │ │ │ ├── BooksPage.scss
│ │ │ │ ├── BooksPage.test.tsx
│ │ │ │ └── BooksPage.tsx
│ │ │ ├── BuildSiteCoursePage
│ │ │ │ ├── BuildSiteCoursePage.scss
│ │ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ │ └── BuildSiteCoursePage.tsx
│ │ │ ├── CoachingHourlyPage
│ │ │ │ ├── CoachingHourlyPage.scss
│ │ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ │ └── CoachingHourlyPage.tsx
│ │ │ ├── CoachingPackagePage
│ │ │ │ ├── CoachingPackagePage.scss
│ │ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ │ └── CoachingPackagePage.tsx
│ │ │ ├── ContactPage
│ │ │ │ ├── ContactPage.scss
│ │ │ │ ├── ContactPage.test.tsx
│ │ │ │ └── ContactPage.tsx
│ │ │ ├── HomePage
│ │ │ │ ├── HomePage.scss
│ │ │ │ ├── HomePage.test.tsx
│ │ │ │ └── HomePage.tsx
│ │ │ ├── LoginPage
│ │ │ │ ├── LoginPage.scss
│ │ │ │ ├── LoginPage.test.tsx
│ │ │ │ └── LoginPage.tsx
│ │ │ ├── MembersPage
│ │ │ │ ├── MembersPage.scss
│ │ │ │ ├── MembersPage.test.tsx
│ │ │ │ └── MembersPage.tsx
│ │ │ ├── NotFoundPage
│ │ │ │ ├── NotFoundPage.scss
│ │ │ │ ├── NotFoundPage.test.tsx
│ │ │ │ └── NotFoundPage.tsx
│ │ │ ├── README
│ │ │ └── YouBuildMySitePage
│ │ │ │ ├── YouBuildMySitePage.scss
│ │ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ │ └── YouBuildMySitePage.tsx
│ │ ├── react-app-env.d.ts
│ │ ├── recoil
│ │ │ ├── atoms
│ │ │ │ ├── README
│ │ │ │ ├── preferencesAtoms.ts
│ │ │ │ └── sessionAtoms.ts
│ │ │ └── selectors
│ │ │ │ └── README
│ │ ├── serviceWorker.ts
│ │ └── setupTests.ts
│ ├── templates
│ │ ├── component
│ │ │ ├── component.js
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ ├── test.js
│ │ │ └── test.tsx
│ │ └── page
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
├── exercise-6-2
│ ├── .DS_Store
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ │ ├── app.test.tsx
│ │ ├── global.d.ts
│ │ ├── jest.config.js
│ │ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── .DS_Store
│ │ ├── App.scss
│ │ ├── App.test.tsx
│ │ ├── App.tsx
│ │ ├── AppRouter.scss
│ │ ├── AppRouter.test.tsx
│ │ ├── AppRouter.tsx
│ │ ├── assets
│ │ │ ├── README
│ │ │ └── toast
│ │ │ │ ├── check.svg
│ │ │ │ ├── error.svg
│ │ │ │ ├── info.svg
│ │ │ │ └── warning.svg
│ │ ├── components
│ │ │ ├── README
│ │ │ ├── Toast
│ │ │ │ ├── Toast.scss
│ │ │ │ ├── Toast.tsx
│ │ │ │ ├── ToastNotification.scss
│ │ │ │ └── ToastNotification.tsx
│ │ │ ├── UserButton
│ │ │ │ ├── UserButton.scss
│ │ │ │ └── UserButton.tsx
│ │ │ └── UserListButton
│ │ │ │ └── UserListButton.tsx
│ │ ├── features
│ │ │ └── README
│ │ ├── index.scss
│ │ ├── index.tsx
│ │ ├── layout
│ │ │ ├── Footer
│ │ │ │ ├── Footer.scss
│ │ │ │ ├── Footer.styles.ts
│ │ │ │ ├── Footer.test.tsx
│ │ │ │ ├── Footer.tsx
│ │ │ │ └── FooterTheme.tsx
│ │ │ ├── Header
│ │ │ │ ├── Header.scss
│ │ │ │ ├── Header.test.tsx
│ │ │ │ ├── Header.tsx
│ │ │ │ ├── HeaderDrawer.tsx
│ │ │ │ ├── HeaderTheme.tsx
│ │ │ │ └── HeaderTopNav.tsx
│ │ │ └── README
│ │ ├── logo.svg
│ │ ├── model
│ │ │ ├── README
│ │ │ ├── index.ts
│ │ │ ├── preferencesObject.ts
│ │ │ └── toastObject.ts
│ │ ├── pages
│ │ │ ├── ArticlesPage
│ │ │ │ ├── ArticlesPage.scss
│ │ │ │ ├── ArticlesPage.test.tsx
│ │ │ │ └── ArticlesPage.tsx
│ │ │ ├── BooksPage
│ │ │ │ ├── BooksPage.scss
│ │ │ │ ├── BooksPage.test.tsx
│ │ │ │ └── BooksPage.tsx
│ │ │ ├── BuildSiteCoursePage
│ │ │ │ ├── BuildSiteCoursePage.scss
│ │ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ │ └── BuildSiteCoursePage.tsx
│ │ │ ├── CoachingHourlyPage
│ │ │ │ ├── CoachingHourlyPage.scss
│ │ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ │ └── CoachingHourlyPage.tsx
│ │ │ ├── CoachingPackagePage
│ │ │ │ ├── CoachingPackagePage.scss
│ │ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ │ └── CoachingPackagePage.tsx
│ │ │ ├── ContactPage
│ │ │ │ ├── ContactPage.scss
│ │ │ │ ├── ContactPage.test.tsx
│ │ │ │ └── ContactPage.tsx
│ │ │ ├── HomePage
│ │ │ │ ├── HomePage.scss
│ │ │ │ ├── HomePage.test.tsx
│ │ │ │ └── HomePage.tsx
│ │ │ ├── LoginPage
│ │ │ │ ├── LoginPage.scss
│ │ │ │ ├── LoginPage.test.tsx
│ │ │ │ └── LoginPage.tsx
│ │ │ ├── MembersPage
│ │ │ │ ├── MembersPage.scss
│ │ │ │ ├── MembersPage.test.tsx
│ │ │ │ └── MembersPage.tsx
│ │ │ ├── NotFoundPage
│ │ │ │ ├── NotFoundPage.scss
│ │ │ │ ├── NotFoundPage.test.tsx
│ │ │ │ └── NotFoundPage.tsx
│ │ │ ├── README
│ │ │ └── YouBuildMySitePage
│ │ │ │ ├── YouBuildMySitePage.scss
│ │ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ │ └── YouBuildMySitePage.tsx
│ │ ├── react-app-env.d.ts
│ │ ├── recoil
│ │ │ ├── atoms
│ │ │ │ ├── README
│ │ │ │ ├── preferencesAtoms.ts
│ │ │ │ ├── sessionAtoms.ts
│ │ │ │ └── toastAtoms.ts
│ │ │ └── selectors
│ │ │ │ └── README
│ │ ├── serviceWorker.ts
│ │ └── setupTests.ts
│ ├── templates
│ │ ├── component
│ │ │ ├── component.js
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ ├── test.js
│ │ │ └── test.tsx
│ │ └── page
│ │ │ ├── component.tsx
│ │ │ ├── style.scss
│ │ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
└── exercise-6-3
│ ├── .DS_Store
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── .DS_Store
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.scss
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ ├── README
│ │ └── toast
│ │ │ ├── check.svg
│ │ │ ├── error.svg
│ │ │ ├── info.svg
│ │ │ └── warning.svg
│ ├── components
│ │ ├── Login
│ │ │ ├── LoginForm.styles.ts
│ │ │ └── LoginForm.tsx
│ │ ├── README
│ │ ├── Toast
│ │ │ ├── Toast.scss
│ │ │ ├── Toast.tsx
│ │ │ ├── ToastNotification.scss
│ │ │ └── ToastNotification.tsx
│ │ ├── UserButton
│ │ │ ├── UserButton.scss
│ │ │ └── UserButton.tsx
│ │ └── UserListButton
│ │ │ └── UserListButton.tsx
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ ├── Centered
│ │ │ ├── Centered.styles.ts
│ │ │ ├── Centered.tsx
│ │ │ └── index.ts
│ │ ├── Footer
│ │ │ ├── Footer.scss
│ │ │ ├── Footer.styles.ts
│ │ │ ├── Footer.test.tsx
│ │ │ ├── Footer.tsx
│ │ │ └── FooterTheme.tsx
│ │ ├── Header
│ │ │ ├── Header.scss
│ │ │ ├── Header.test.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── HeaderDrawer.tsx
│ │ │ ├── HeaderTheme.tsx
│ │ │ └── HeaderTopNav.tsx
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ ├── README
│ │ ├── index.ts
│ │ ├── preferencesObject.ts
│ │ ├── toastObject.ts
│ │ └── userObject.ts
│ ├── pages
│ │ ├── ArticlesPage
│ │ │ ├── ArticlesPage.scss
│ │ │ ├── ArticlesPage.test.tsx
│ │ │ └── ArticlesPage.tsx
│ │ ├── BooksPage
│ │ │ ├── BooksPage.scss
│ │ │ ├── BooksPage.test.tsx
│ │ │ └── BooksPage.tsx
│ │ ├── BuildSiteCoursePage
│ │ │ ├── BuildSiteCoursePage.scss
│ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ └── BuildSiteCoursePage.tsx
│ │ ├── CoachingHourlyPage
│ │ │ ├── CoachingHourlyPage.scss
│ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ └── CoachingHourlyPage.tsx
│ │ ├── CoachingPackagePage
│ │ │ ├── CoachingPackagePage.scss
│ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ └── CoachingPackagePage.tsx
│ │ ├── ContactPage
│ │ │ ├── ContactPage.scss
│ │ │ ├── ContactPage.test.tsx
│ │ │ └── ContactPage.tsx
│ │ ├── HomePage
│ │ │ ├── HomePage.scss
│ │ │ ├── HomePage.test.tsx
│ │ │ └── HomePage.tsx
│ │ ├── LoginPage
│ │ │ ├── LoginPage.scss
│ │ │ ├── LoginPage.test.tsx
│ │ │ └── LoginPage.tsx
│ │ ├── MembersPage
│ │ │ ├── MembersHome.tsx
│ │ │ ├── MembersPage.scss
│ │ │ └── MembersPage.tsx
│ │ ├── NotFoundPage
│ │ │ ├── NotFoundPage.scss
│ │ │ ├── NotFoundPage.test.tsx
│ │ │ └── NotFoundPage.tsx
│ │ ├── README
│ │ └── YouBuildMySitePage
│ │ │ ├── YouBuildMySitePage.scss
│ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ └── YouBuildMySitePage.tsx
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ ├── README
│ │ │ ├── preferencesAtoms.ts
│ │ │ ├── sessionAtoms.ts
│ │ │ ├── toastAtoms.ts
│ │ │ └── userAtoms.ts
│ │ └── selectors
│ │ │ ├── README
│ │ │ └── userSelectors.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
├── Ch7
├── .DS_Store
├── exercise-7-1
│ ├── .DS_Store
│ ├── config.json
│ ├── logs
│ │ ├── server-error.log
│ │ └── server.log
│ ├── models
│ │ └── database.js
│ ├── package-lock.json
│ ├── package.json
│ ├── roomsdb-local.json
│ ├── roomsdb.json
│ ├── server.js
│ ├── services
│ │ ├── register.js
│ │ └── validate.js
│ └── utils
│ │ └── log.js
└── exercise-7-2
│ ├── .DS_Store
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── .DS_Store
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.scss
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ ├── README
│ │ └── toast
│ │ │ ├── check.svg
│ │ │ ├── error.svg
│ │ │ ├── info.svg
│ │ │ └── warning.svg
│ ├── components
│ │ ├── Login
│ │ │ ├── LoginForm.styles.ts
│ │ │ └── LoginForm.tsx
│ │ ├── README
│ │ ├── Register
│ │ │ ├── RegisterForm.styles.ts
│ │ │ └── RegisterForm.tsx
│ │ ├── Toast
│ │ │ ├── Toast.scss
│ │ │ ├── Toast.tsx
│ │ │ ├── ToastNotification.scss
│ │ │ └── ToastNotification.tsx
│ │ ├── UserButton
│ │ │ ├── UserButton.scss
│ │ │ └── UserButton.tsx
│ │ └── UserListButton
│ │ │ └── UserListButton.tsx
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ ├── Centered
│ │ │ ├── Centered.styles.ts
│ │ │ ├── Centered.tsx
│ │ │ └── index.ts
│ │ ├── Footer
│ │ │ ├── Footer.scss
│ │ │ ├── Footer.styles.ts
│ │ │ ├── Footer.test.tsx
│ │ │ ├── Footer.tsx
│ │ │ └── FooterTheme.tsx
│ │ ├── Header
│ │ │ ├── Header.scss
│ │ │ ├── Header.test.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── HeaderDrawer.tsx
│ │ │ ├── HeaderTheme.tsx
│ │ │ └── HeaderTopNav.tsx
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ ├── README
│ │ ├── index.ts
│ │ ├── preferencesObject.ts
│ │ ├── registerObject.ts
│ │ ├── toastObject.ts
│ │ └── userObject.ts
│ ├── pages
│ │ ├── ArticlesPage
│ │ │ ├── ArticlesPage.scss
│ │ │ ├── ArticlesPage.test.tsx
│ │ │ └── ArticlesPage.tsx
│ │ ├── BooksPage
│ │ │ ├── BooksPage.scss
│ │ │ ├── BooksPage.test.tsx
│ │ │ └── BooksPage.tsx
│ │ ├── BuildSiteCoursePage
│ │ │ ├── BuildSiteCoursePage.scss
│ │ │ ├── BuildSiteCoursePage.test.tsx
│ │ │ └── BuildSiteCoursePage.tsx
│ │ ├── CoachingHourlyPage
│ │ │ ├── CoachingHourlyPage.scss
│ │ │ ├── CoachingHourlyPage.test.tsx
│ │ │ └── CoachingHourlyPage.tsx
│ │ ├── CoachingPackagePage
│ │ │ ├── CoachingPackagePage.scss
│ │ │ ├── CoachingPackagePage.test.tsx
│ │ │ └── CoachingPackagePage.tsx
│ │ ├── ContactPage
│ │ │ ├── ContactPage.scss
│ │ │ ├── ContactPage.test.tsx
│ │ │ └── ContactPage.tsx
│ │ ├── HomePage
│ │ │ ├── HomePage.scss
│ │ │ ├── HomePage.test.tsx
│ │ │ └── HomePage.tsx
│ │ ├── LoginPage
│ │ │ ├── LoginPage.scss
│ │ │ ├── LoginPage.test.tsx
│ │ │ └── LoginPage.tsx
│ │ ├── MembersPage
│ │ │ ├── MembersHome.tsx
│ │ │ ├── MembersPage.scss
│ │ │ └── MembersPage.tsx
│ │ ├── NotFoundPage
│ │ │ ├── NotFoundPage.scss
│ │ │ ├── NotFoundPage.test.tsx
│ │ │ └── NotFoundPage.tsx
│ │ ├── README
│ │ ├── RegisterPage
│ │ │ ├── RegisterPage.scss
│ │ │ ├── RegisterPage.test.tsx
│ │ │ └── RegisterPage.tsx
│ │ └── YouBuildMySitePage
│ │ │ ├── YouBuildMySitePage.scss
│ │ │ ├── YouBuildMySitePage.test.tsx
│ │ │ └── YouBuildMySitePage.tsx
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ ├── README
│ │ │ ├── preferencesAtoms.ts
│ │ │ ├── registerAtoms.ts
│ │ │ ├── sessionAtoms.ts
│ │ │ ├── toastAtoms.ts
│ │ │ └── userAtoms.ts
│ │ └── selectors
│ │ │ ├── README
│ │ │ ├── registerSelectors.ts
│ │ │ └── userSelectors.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
│ ├── tsconfig.json
│ └── yarn.lock
├── Ch8
├── .DS_Store
├── api
│ └── Gruntfile.js
└── app
│ ├── .DS_Store
│ └── Gruntfile.js
├── Ch9
├── .DS_Store
└── hello-jest-enzyme-ts
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── README_CRA.md
│ ├── e2e
│ ├── app.test.tsx
│ ├── global.d.ts
│ ├── jest.config.js
│ └── puppeteer_standalone.js
│ ├── generate-react-cli.json
│ ├── jest-puppeteer.config.js
│ ├── package.json
│ ├── public
│ ├── calculator-input.jpg
│ ├── calculator.jpg
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
│ ├── src
│ ├── App.scss
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AppRouter.test.tsx
│ ├── AppRouter.tsx
│ ├── assets
│ │ └── README
│ ├── components
│ │ ├── Calculator
│ │ │ ├── Calculator.scss
│ │ │ ├── Calculator.test.tsx
│ │ │ ├── Calculator.tsx
│ │ │ └── __snapshots__
│ │ │ │ └── Calculator.test.tsx.snap
│ │ └── README
│ ├── features
│ │ └── README
│ ├── index.scss
│ ├── index.tsx
│ ├── layout
│ │ └── README
│ ├── logo.svg
│ ├── model
│ │ └── README
│ ├── pages
│ │ └── README
│ ├── react-app-env.d.ts
│ ├── recoil
│ │ ├── atoms
│ │ │ └── README
│ │ └── selectors
│ │ │ └── README
│ ├── redux
│ │ └── store.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
│ ├── templates
│ ├── component
│ │ ├── component.js
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ ├── test.js
│ │ └── test.tsx
│ └── page
│ │ ├── component.tsx
│ │ ├── style.scss
│ │ └── test.tsx
│ └── tsconfig.json
├── Contributing.md
├── LICENSE.txt
├── README.md
└── errata.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/9781484266953.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/9781484266953.jpg
--------------------------------------------------------------------------------
/Ch1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch1/.DS_Store
--------------------------------------------------------------------------------
/Ch1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello world
5 |
6 |
7 |
9 |
10 |
11 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Ch10/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/.DS_Store
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/.env:
--------------------------------------------------------------------------------
1 | SKIP_PREFLIGHT_CHECK=true
2 | BROWSER=none
3 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*
2 | public/*
3 | docs/*
4 | templates/*
5 | src/react-app-env.d.ts
6 | src/serviceWorker.ts
7 | e2e/jest.config.js
8 | e2e/puppeteer_standalone.js
9 | jest-puppeteer.config.js
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/.gitignore:
--------------------------------------------------------------------------------
1 | # misc
2 | .DS_Store
3 | package-lock.json
4 | yarn-error.log
5 | yarn.lock
6 | docs
7 |
8 | # IDE
9 | .idea
10 |
11 | # dependencies
12 | /node_modules
13 | /.pnp
14 | .pnp.js
15 |
16 | # testing
17 | /coverage
18 | .nyc_output
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | .env.local
26 | .env.development.local
27 | .env.test.local
28 | .env.production.local
29 |
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "printWidth": 100,
4 | "semi": false,
5 | "singleQuote": true,
6 | "tabWidth": 2
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/favicon.ico
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/logo192.png
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/logo512.png
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import logo from './logo.svg'
3 | import './App.scss'
4 |
5 | function App() {
6 | return (
7 |
23 | )
24 | }
25 |
26 | export default App
27 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | }
8 |
9 | code {
10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
11 | }
12 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 |
5 | const store = configureStore({
6 | reducer: combineReducers({
7 | // your reducers goes here
8 | }),
9 | })
10 |
11 | export default store
12 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch10/e2e_ts_testing_with_puppeteer/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch12/.env:
--------------------------------------------------------------------------------
1 | SKIP_PREFLIGHT_CHECK=true
2 | BROWSER=none
3 |
--------------------------------------------------------------------------------
/Ch12/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*
2 | public/*
3 | docs/*
4 | templates/*
5 | src/react-app-env.d.ts
6 | src/serviceWorker.ts
7 | e2e/jest.config.js
8 | e2e/puppeteer_standalone.js
9 | jest-puppeteer.config.js
--------------------------------------------------------------------------------
/Ch12/.gitignore:
--------------------------------------------------------------------------------
1 | # misc
2 | .DS_Store
3 | package-lock.json
4 | yarn-error.log
5 | yarn.lock
6 | docs
7 |
8 | # IDEs
9 | .vscode
10 | .idea
11 |
12 | # dependencies
13 | /node_modules
14 | /.pnp
15 | .pnp.js
16 |
17 | # testing
18 | /coverage
19 | .nyc_output
20 |
21 | # production
22 | /build
23 |
24 | # misc
25 | .DS_Store
26 | .env.local
27 | .env.development.local
28 | .env.test.local
29 | .env.production.local
30 |
31 | npm-debug.log*
32 | yarn-debug.log*
33 | yarn-error.log*
34 |
--------------------------------------------------------------------------------
/Ch12/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "printWidth": 100,
4 | "semi": false,
5 | "singleQuote": true,
6 | "tabWidth": 2
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/Ch12/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch12/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 10000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch12/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch12/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/favicon.ico
--------------------------------------------------------------------------------
/Ch12/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/logo192.png
--------------------------------------------------------------------------------
/Ch12/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/logo512.png
--------------------------------------------------------------------------------
/Ch12/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch12/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch12/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch12/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch12/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch12/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch12/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch12/src/components/ScrollToTop/ScrollToTop.tsx:
--------------------------------------------------------------------------------
1 | // src/components/ScrollToTop/ScrollToTop.tsx
2 |
3 | import { useEffect } from 'react'
4 | import { useLocation } from 'react-router-dom'
5 |
6 | export default function ScrollToTop() {
7 | const { pathname, search } = useLocation()
8 |
9 | useEffect(
10 | () => () => {
11 | try {
12 | window.scroll({
13 | top: 0,
14 | left: 0,
15 | behavior: 'smooth',
16 | })
17 | } catch (error) {
18 | // older browsers fallback
19 | window.scrollTo(0, 0)
20 | }
21 | },
22 | [pathname, search]
23 | )
24 | return null
25 | }
26 |
--------------------------------------------------------------------------------
/Ch12/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch12/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | }
8 |
9 | code {
10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
11 | }
12 |
--------------------------------------------------------------------------------
/Ch12/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch12/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch12/src/pages/MyPage/MyPage.scss:
--------------------------------------------------------------------------------
1 | .MyPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch12/src/pages/MyPage/MyPage.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import MyPage from './MyPage'
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/MyPage',
9 | },
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch12/src/pages/MyPage/math.tsx:
--------------------------------------------------------------------------------
1 | // src/page/MyPage/math.tsx
2 |
3 | export function square(x: number) {
4 | return x * x
5 | }
6 |
7 | export function cube(x: number) {
8 | return x * x * x
9 | }
10 |
11 | export function add(x: number, y: number) {
12 | return x + y
13 | }
14 |
--------------------------------------------------------------------------------
/Ch12/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch12/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch12/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch12/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 |
5 | const store = configureStore({
6 | reducer: combineReducers({
7 | // your reducers goes here
8 | }),
9 | })
10 |
11 | export default store
12 |
--------------------------------------------------------------------------------
/Ch12/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch12/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch12/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch12/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch12/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch12/templates/page/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/TemplateName'
9 | }
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/.DS_Store
--------------------------------------------------------------------------------
/Ch2/hello-cra/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/favicon.ico
--------------------------------------------------------------------------------
/Ch2/hello-cra/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/logo192.png
--------------------------------------------------------------------------------
/Ch2/hello-cra/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/logo512.png
--------------------------------------------------------------------------------
/Ch2/hello-cra/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import logo from './logo.svg';
3 | import './App.css';
4 |
5 | function App() {
6 | return (
7 |
23 | );
24 | }
25 |
26 | export default App;
27 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | const { getByText } = render();
7 | const linkElement = getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | );
13 |
14 | // If you want your app to work offline and load faster, you can change
15 | // unregister() to register() below. Note this comes with some pitfalls.
16 | // Learn more about service workers: https://bit.ly/CRA-PWA
17 | serviceWorker.unregister();
18 |
--------------------------------------------------------------------------------
/Ch2/hello-cra/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect';
6 |
--------------------------------------------------------------------------------
/Ch2/starter-project/.gitignore:
--------------------------------------------------------------------------------
1 | # misc
2 | .DS_Store
3 | package-lock.json
4 | docs
5 |
6 | # IDE
7 | .idea
8 |
9 | # dependencies
10 | /node_modules
11 |
12 | # dependencies
13 | /node_modules
14 | /.pnp
15 | .pnp.js
16 |
17 | # testing
18 | /coverage
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | .env.local
26 | .env.development.local
27 | .env.test.local
28 | .env.production.local
29 |
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 |
--------------------------------------------------------------------------------
/Ch2/starter-project/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "printWidth": 100,
4 | "semi": false,
5 | "singleQuote": true,
6 | "tabWidth": 2
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/Ch2/starter-project/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/favicon.ico
--------------------------------------------------------------------------------
/Ch2/starter-project/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/logo192.png
--------------------------------------------------------------------------------
/Ch2/starter-project/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/logo512.png
--------------------------------------------------------------------------------
/Ch2/starter-project/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch2/starter-project/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from '@testing-library/react'
3 | import App from './App'
4 |
5 | test('renders learn react link', () => {
6 | const { getByText } = render()
7 | const linkElement = getByText(/learn react/i)
8 | expect(linkElement).toBeInTheDocument()
9 | })
10 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import logo from './logo.svg'
3 | import './App.css'
4 |
5 | function App() {
6 | return (
7 |
23 | )
24 | }
25 |
26 | export default App
27 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | }
8 |
9 | code {
10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
11 | }
12 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './index.css'
4 | import App from './App'
5 | import * as serviceWorker from './serviceWorker'
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | )
13 |
14 | // If you want your app to work offline and load faster, you can change
15 | // unregister() to register() below. Note this comes with some pitfalls.
16 | // Learn more about service workers: https://bit.ly/CRA-PWA
17 | serviceWorker.unregister()
18 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch2/starter-project/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
--------------------------------------------------------------------------------
/Ch2/starter-project/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
--------------------------------------------------------------------------------
/Ch2/starter-project/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch2/starter-project/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "es6", "dom",
6 | "dom",
7 | "dom.iterable",
8 | "esnext"
9 | ],
10 | "noImplicitAny": true,
11 | "noImplicitThis": true,
12 | "strictNullChecks": true,
13 | "allowJs": true,
14 | "skipLibCheck": true,
15 | "esModuleInterop": true,
16 | "allowSyntheticDefaultImports": true,
17 | "strict": true,
18 | "forceConsistentCasingInFileNames": true,
19 | "module": "esnext",
20 | "moduleResolution": "node",
21 | "resolveJsonModule": true,
22 | "isolatedModules": true,
23 | "noEmit": true,
24 | "jsx": "react"
25 | },
26 | "include": [
27 | "src"
28 | ]
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/Ch3/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch3/.DS_Store
--------------------------------------------------------------------------------
/Ch3/WelcomeUser.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hi
5 |
6 |
7 |
9 |
10 |
11 |
12 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Ch4/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/.DS_Store
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/favicon.ico
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/logo192.png
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/logo512.png
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/src/.DS_Store
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 |
6 | function App() {
7 | return (
8 |
11 | )
12 | }
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | code {
9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
10 | }
11 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Footer/Footer.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: Footer.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './Footer.scss'
10 |
11 | export default class Footer extends React.PureComponent {
12 | constructor(props: IFooterProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return <>Footer>
19 | }
20 | }
21 |
22 | interface IFooterProps {
23 | // TODO
24 | }
25 |
26 | interface IFooterState {
27 | // TODO
28 | }
29 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/Header/Header.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: Header.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './Header.scss'
10 |
11 | export default class Header extends React.PureComponent {
12 | constructor(props: IHeaderProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return <>Header>
19 | }
20 | }
21 |
22 | interface IHeaderProps {
23 | // TODO
24 | }
25 |
26 | interface IHeaderState {
27 | // TODO
28 | }
29 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/HomePage/HomePage.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import HomePage from './HomePage'
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/HomePage',
9 | },
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | }
3 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 |
5 | const store = configureStore({
6 | reducer: combineReducers({
7 | // your reducers goes here
8 | }),
9 | })
10 |
11 | export default store
12 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-1/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-2/.DS_Store
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-2/public/favicon.ico
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-2/public/logo192.png
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-2/public/logo512.png
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-2/src/.DS_Store
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | }
5 |
6 | .App-logo {
7 | height: 40vmin;
8 | pointer-events: none;
9 | }
10 |
11 | @media (prefers-reduced-motion: no-preference) {
12 | .App-logo {
13 | animation: App-logo-spin infinite 20s linear;
14 | }
15 | }
16 |
17 | .App-header {
18 | background-color: #282c34;
19 | min-height: 100vh;
20 | display: flex;
21 | flex-direction: column;
22 | align-items: center;
23 | justify-content: center;
24 | font-size: calc(10px + 2vmin);
25 | color: white;
26 | }
27 |
28 | .App-link {
29 | color: #61dafb;
30 | }
31 |
32 | @keyframes App-logo-spin {
33 | from {
34 | transform: rotate(0deg);
35 | }
36 | to {
37 | transform: rotate(360deg);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 |
6 | function App() {
7 | return (
8 |
11 | )
12 | }
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | code {
9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
10 | }
11 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | position: relative;
3 | padding-top: 500px;
4 | padding-left: 20px;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Footer/Footer.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: Footer.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './Footer.scss'
10 |
11 | export default class Footer extends React.PureComponent {
12 | constructor(props: IFooterProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return Footer
19 | }
20 | }
21 |
22 | interface IFooterProps {
23 | // TODO
24 | }
25 |
26 | interface IFooterState {
27 | // TODO
28 | }
29 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/Header/HeaderTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Header/HeaderTheme.tsx
2 |
3 | import React, { FunctionComponent } from 'react'
4 | import AppBar from '@material-ui/core/AppBar/AppBar'
5 | import { useMediaQuery } from '@material-ui/core'
6 | import HeaderComponent from './Header'
7 |
8 | function appBarBackgroundStyle() {
9 | return {
10 | background: '000000',
11 | }
12 | }
13 |
14 | export const HeaderTheme: FunctionComponent = () => {
15 | const smallBreakPoint = useMediaQuery('(min-width: 0px) and (max-width: 1100px)')
16 | return (
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 |
5 | const store = configureStore({
6 | reducer: combineReducers({
7 | // your reducers goes here
8 | }),
9 | })
10 |
11 | export default store
12 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch4/exercise-4-2/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch5/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch5/.DS_Store
--------------------------------------------------------------------------------
/Ch5/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch5/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch5/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch5/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch5/public/favicon.ico
--------------------------------------------------------------------------------
/Ch5/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch5/public/logo192.png
--------------------------------------------------------------------------------
/Ch5/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch5/public/logo512.png
--------------------------------------------------------------------------------
/Ch5/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch5/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch5/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch5/src/.DS_Store
--------------------------------------------------------------------------------
/Ch5/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | height: 350px;
5 | }
6 |
7 | .App-logo {
8 | height: 40vmin;
9 | pointer-events: none;
10 | }
11 |
12 | @media (prefers-reduced-motion: no-preference) {
13 | .App-logo {
14 | animation: App-logo-spin infinite 20s linear;
15 | }
16 | }
17 |
18 | .App-header {
19 | background-color: #282c34;
20 | min-height: 100vh;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | font-size: calc(10px + 2vmin);
26 | color: white;
27 | }
28 |
29 | .App-link {
30 | color: #61dafb;
31 | }
32 |
33 | @keyframes App-logo-spin {
34 | from {
35 | transform: rotate(0deg);
36 | }
37 | to {
38 | transform: rotate(360deg);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ch5/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch5/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 |
6 | function App() {
7 | return (
8 |
11 | )
12 | }
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/Ch5/src/AppRouter.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | width: 100%;
3 | position: fixed;
4 | bottom: 0%;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch5/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch5/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch5/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch5/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch5/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | .dark {
9 | color: white;
10 | background-color: #2b2b2b;
11 | }
12 |
13 | .light {
14 | color: black;
15 | background-color: darkgrey;
16 | }
17 |
--------------------------------------------------------------------------------
/Ch5/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch5/src/layout/Footer/FooterTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Footer/FooterTheme.tsx
2 |
3 | import React, { FunctionComponent, useState } from 'react'
4 | import { ThemeEnum } from '../../model'
5 | import store from '../../redux/store'
6 | import FooterComponent from './Footer'
7 |
8 | export const FooterTheme: FunctionComponent = () => {
9 | const [theme, setTheme] = useState(ThemeEnum.Light)
10 | store.subscribe(() => {
11 | setTheme(store.getState().preferences.theme)
12 | })
13 | return
14 | }
15 |
--------------------------------------------------------------------------------
/Ch5/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch5/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch5/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch5/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch5/src/model/index.ts:
--------------------------------------------------------------------------------
1 | // src/model/index.ts
2 | export * from './preferencesObject'
3 |
--------------------------------------------------------------------------------
/Ch5/src/model/preferencesObject.ts:
--------------------------------------------------------------------------------
1 | // src/model/preferencesObject.ts
2 |
3 | export enum ThemeEnum {
4 | Dark = 'dark',
5 | Light = 'light',
6 | }
7 |
--------------------------------------------------------------------------------
/Ch5/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/BooksPage/BooksPage.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import BooksPage from './BooksPage'
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/BooksPage',
9 | },
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch5/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/HomePage/HomePage.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import HomePage from './HomePage'
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/HomePage',
9 | },
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch5/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/LoginPage/LoginPage.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import LoginPage from './LoginPage'
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/LoginPage',
9 | },
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch5/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch5/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch5/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch5/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch5/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 | import prefSlice from '../features/Preferences/preferencesSlice'
5 |
6 | const store = configureStore({
7 | reducer: combineReducers({
8 | preferences: prefSlice,
9 | }),
10 | })
11 |
12 | export default store
13 |
--------------------------------------------------------------------------------
/Ch5/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch5/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch5/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch5/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch5/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch5/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch5/templates/page/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | const routeComponentPropsMock = {
6 | history: {
7 | location: {
8 | pathname: '/TemplateName'
9 | }
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | } as any,
12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
13 | location: {} as any,
14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
15 | match: {} as any,
16 | }
17 | describe('', () => {
18 | let component
19 |
20 | beforeEach(() => {
21 | component = shallow()
22 | })
23 |
24 | test('It should mount', () => {
25 | expect(component.length).toBe(1)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-1/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-1/public/favicon.ico
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-1/public/logo192.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-1/public/logo512.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-1/src/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | height: 350px;
5 | }
6 |
7 | .App-logo {
8 | height: 40vmin;
9 | pointer-events: none;
10 | }
11 |
12 | @media (prefers-reduced-motion: no-preference) {
13 | .App-logo {
14 | animation: App-logo-spin infinite 20s linear;
15 | }
16 | }
17 |
18 | .App-header {
19 | background-color: #282c34;
20 | min-height: 100vh;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | font-size: calc(10px + 2vmin);
26 | color: white;
27 | }
28 |
29 | .App-link {
30 | color: #61dafb;
31 | }
32 |
33 | @keyframes App-logo-spin {
34 | from {
35 | transform: rotate(0deg);
36 | }
37 | to {
38 | transform: rotate(360deg);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 |
6 | function App() {
7 | return (
8 |
11 | )
12 | }
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/AppRouter.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | width: 100%;
3 | position: fixed;
4 | bottom: 0%;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/components/UserButton/UserButton.scss:
--------------------------------------------------------------------------------
1 | .MemberButton {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | .dark {
9 | color: white;
10 | background-color: #2b2b2b;
11 | }
12 |
13 | .light {
14 | color: black;
15 | background-color: darkgrey;
16 | }
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/Footer/FooterTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Footer/FooterTheme.tsx
2 |
3 | import React, { FunctionComponent } from 'react'
4 | import { useRecoilState } from 'recoil'
5 | import FooterComponent from './Footer'
6 |
7 | import { preferencesState } from '../../recoil/atoms/preferencesAtoms'
8 |
9 | export const FooterTheme: FunctionComponent = () => {
10 | const [preferences] = useRecoilState(preferencesState)
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/model/index.ts:
--------------------------------------------------------------------------------
1 | // src/model/index.ts
2 | export * from './preferencesObject'
3 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/model/preferencesObject.ts:
--------------------------------------------------------------------------------
1 | // src/model/preferencesObject.ts
2 |
3 | export enum ThemeEnum {
4 | Dark = 'dark',
5 | Light = 'light',
6 | }
7 | // eslint-disable-next-line @typescript-eslint/naming-convention
8 | export interface preferencesObject {
9 | theme: ThemeEnum
10 | }
11 |
12 | export const initPreferencesObject = (): preferencesObject => ({
13 | theme: ThemeEnum.Light,
14 | })
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/recoil/atoms/preferencesAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/preferencesAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initPreferencesObject } from '../../model/preferencesObject'
5 |
6 | export const preferencesState = atom({
7 | key: 'PreferencesState',
8 | default: initPreferencesObject(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/recoil/atoms/sessionAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/sessionAtoms.ts
2 | import { atom } from 'recoil'
3 |
4 | export const sessionState = atom({
5 | key: 'SessionState',
6 | default: '',
7 | })
8 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-1/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-2/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-2/public/favicon.ico
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-2/public/logo192.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-2/public/logo512.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-2/src/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | height: 350px;
5 | }
6 |
7 | .App-logo {
8 | height: 40vmin;
9 | pointer-events: none;
10 | }
11 |
12 | @media (prefers-reduced-motion: no-preference) {
13 | .App-logo {
14 | animation: App-logo-spin infinite 20s linear;
15 | }
16 | }
17 |
18 | .App-header {
19 | background-color: #282c34;
20 | min-height: 100vh;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | font-size: calc(10px + 2vmin);
26 | color: white;
27 | }
28 |
29 | .App-link {
30 | color: #61dafb;
31 | }
32 |
33 | @keyframes App-logo-spin {
34 | from {
35 | transform: rotate(0deg);
36 | }
37 | to {
38 | transform: rotate(360deg);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 | import { useSetRecoilState } from 'recoil'
6 | import { toastState } from './recoil/atoms/toastAtoms'
7 | import { initToast, notificationTypesEnums, randomToastId } from './model'
8 |
9 | function App() {
10 | const setToastState = useSetRecoilState(toastState)
11 | setToastState(initToast(randomToastId(), notificationTypesEnums.Success, 'Hello World'))
12 | return (
13 |
16 | )
17 | }
18 |
19 | export default App
20 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/AppRouter.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | width: 100%;
3 | position: fixed;
4 | bottom: 0%;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/assets/toast/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/assets/toast/error.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/assets/toast/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/components/Toast/ToastNotification.scss:
--------------------------------------------------------------------------------
1 | .toast-buttons {
2 | display: flex;
3 | }
4 |
5 | .toast-buttons button {
6 | color: white;
7 | font-size: 14px;
8 | font-weight: bold;
9 | width: 100px;
10 | height: 50px;
11 | margin: 0 10px;
12 | border: none;
13 | outline: none;
14 | }
15 |
16 | .select {
17 | display: flex;
18 | width: 30%;
19 | margin-top: 10px;
20 | }
21 |
22 | .position-select {
23 | background-color: inherit;
24 | color: #fff;
25 | width: 100%;
26 | height: 30px;
27 | font-size: 16px;
28 | }
29 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/components/UserButton/UserButton.scss:
--------------------------------------------------------------------------------
1 | .MemberButton {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | .dark {
9 | color: white;
10 | background-color: #2b2b2b;
11 | }
12 |
13 | .light {
14 | color: black;
15 | background-color: darkgrey;
16 | }
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/Footer/FooterTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Footer/FooterTheme.tsx
2 |
3 | import React, { FunctionComponent } from 'react'
4 | import { useRecoilState } from 'recoil'
5 | import FooterComponent from './Footer'
6 |
7 | import { preferencesState } from '../../recoil/atoms/preferencesAtoms'
8 |
9 | export const FooterTheme: FunctionComponent = () => {
10 | const [preferences] = useRecoilState(preferencesState)
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/model/index.ts:
--------------------------------------------------------------------------------
1 | // src/model/index.ts
2 | export * from './preferencesObject'
3 | export * from './toastObject'
4 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/model/preferencesObject.ts:
--------------------------------------------------------------------------------
1 | // src/model/preferencesObject.ts
2 |
3 | export enum ThemeEnum {
4 | Dark = 'dark',
5 | Light = 'light',
6 | }
7 | // eslint-disable-next-line @typescript-eslint/naming-convention
8 | export interface preferencesObject {
9 | theme: ThemeEnum
10 | }
11 |
12 | export const initPreferencesObject = (): preferencesObject => ({
13 | theme: ThemeEnum.Light,
14 | })
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/recoil/atoms/preferencesAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/preferencesAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initPreferencesObject } from '../../model/preferencesObject'
5 |
6 | export const preferencesState = atom({
7 | key: 'PreferencesState',
8 | default: initPreferencesObject(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/recoil/atoms/sessionAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/sessionAtoms.ts
2 | import { atom } from 'recoil'
3 |
4 | export const sessionState = atom({
5 | key: 'SessionState',
6 | default: '',
7 | })
8 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/recoil/atoms/toastAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/contactAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initEmptyToast } from '../../model'
5 |
6 | export const toastState = atom({
7 | key: 'ToastState',
8 | default: initEmptyToast(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-2/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-3/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-3/public/favicon.ico
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-3/public/logo192.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-3/public/logo512.png
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch6/exercise-6-3/src/.DS_Store
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | height: 350px;
5 | }
6 |
7 | .App-logo {
8 | height: 40vmin;
9 | pointer-events: none;
10 | }
11 |
12 | @media (prefers-reduced-motion: no-preference) {
13 | .App-logo {
14 | animation: App-logo-spin infinite 20s linear;
15 | }
16 | }
17 |
18 | .App-header {
19 | background-color: #282c34;
20 | min-height: 100vh;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | font-size: calc(10px + 2vmin);
26 | color: white;
27 | }
28 |
29 | .App-link {
30 | color: #61dafb;
31 | }
32 |
33 | @keyframes App-logo-spin {
34 | from {
35 | transform: rotate(0deg);
36 | }
37 | to {
38 | transform: rotate(360deg);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 | /*
6 | import { useSetRecoilState } from 'recoil'
7 | import { toastState } from './recoil/atoms/toastAtoms'
8 | import { initToast, notificationTypesEnums, randomToastId } from './model'
9 | */
10 |
11 | function App() {
12 | // const setToastState = useSetRecoilState(toastState)
13 | // setToastState(initToast(randomToastId(), notificationTypesEnums.Success, 'Hello World'))
14 | return (
15 |
18 | )
19 | }
20 |
21 | export default App
22 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/AppRouter.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | width: 100%;
3 | position: fixed;
4 | bottom: 0%;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/assets/toast/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/assets/toast/error.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/assets/toast/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/components/Login/LoginForm.styles.ts:
--------------------------------------------------------------------------------
1 | // src/components/Login/LoginForm.styles.ts
2 |
3 | import { createStyles, Theme } from '@material-ui/core/styles'
4 |
5 | export default (theme: Theme) =>
6 | createStyles({
7 | container: {
8 | display: 'flex',
9 | flexDirection: 'column',
10 | justifyContent: 'center',
11 | },
12 | })
13 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/components/Toast/ToastNotification.scss:
--------------------------------------------------------------------------------
1 | .toast-buttons {
2 | display: flex;
3 | }
4 |
5 | .toast-buttons button {
6 | color: white;
7 | font-size: 14px;
8 | font-weight: bold;
9 | width: 100px;
10 | height: 50px;
11 | margin: 0 10px;
12 | border: none;
13 | outline: none;
14 | }
15 |
16 | .select {
17 | display: flex;
18 | width: 30%;
19 | margin-top: 10px;
20 | }
21 |
22 | .position-select {
23 | background-color: inherit;
24 | color: #fff;
25 | width: 100%;
26 | height: 30px;
27 | font-size: 16px;
28 | }
29 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/components/UserButton/UserButton.scss:
--------------------------------------------------------------------------------
1 | .MemberButton {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | }
7 |
8 | .dark {
9 | color: white;
10 | background-color: #2b2b2b;
11 | }
12 |
13 | .light {
14 | color: black;
15 | background-color: darkgrey;
16 | }
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Centered/Centered.styles.ts:
--------------------------------------------------------------------------------
1 | // src/layout/Centered/Centered.styles.ts
2 |
3 | import { createStyles, Theme } from '@material-ui/core/styles'
4 |
5 | export default (theme: Theme) =>
6 | createStyles({
7 | '@global': {
8 | 'body, html, #root': {
9 | paddingTop: 40,
10 | width: '100%',
11 | },
12 | },
13 | container: {
14 | maxWidth: '400px',
15 | margin: '0 auto',
16 | },
17 | })
18 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Centered/Centered.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: src/layout/Centered/Centered.tsx
6 | */
7 |
8 | import * as React from 'react'
9 | import { withStyles, WithStyles } from '@material-ui/core/styles'
10 | import styles from './Centered.styles'
11 |
12 | const CenteredViewInner: React.FunctionComponent = (props) => {props.children}
13 |
14 | interface Props extends WithStyles {}
15 |
16 | export const Centered = withStyles(styles)(CenteredViewInner)
17 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Centered/index.ts:
--------------------------------------------------------------------------------
1 | // src/layout/index.ts
2 | export { Centered } from './Centered'
3 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Footer/FooterTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Footer/FooterTheme.tsx
2 |
3 | import React, { FunctionComponent } from 'react'
4 | import { useRecoilState } from 'recoil'
5 | import FooterComponent from './Footer'
6 |
7 | import { preferencesState } from '../../recoil/atoms/preferencesAtoms'
8 |
9 | export const FooterTheme: FunctionComponent = () => {
10 | const [preferences] = useRecoilState(preferencesState)
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/model/index.ts:
--------------------------------------------------------------------------------
1 | // src/model/index.ts
2 | export * from './preferencesObject'
3 | export * from './toastObject'
4 | export * from './userObject'
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/model/preferencesObject.ts:
--------------------------------------------------------------------------------
1 | // src/model/preferencesObject.ts
2 |
3 | export enum ThemeEnum {
4 | Dark = 'dark',
5 | Light = 'light',
6 | }
7 | // eslint-disable-next-line @typescript-eslint/naming-convention
8 | export interface preferencesObject {
9 | theme: ThemeEnum
10 | }
11 |
12 | export const initPreferencesObject = (): preferencesObject => ({
13 | theme: ThemeEnum.Light,
14 | })
15 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/model/userObject.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/naming-convention
2 | export interface userObject {
3 | email: string
4 | password: string
5 | }
6 |
7 | export const initUser = (): userObject => ({
8 | email: '',
9 | password: '',
10 | })
11 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/recoil/atoms/preferencesAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/preferencesAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initPreferencesObject } from '../../model/preferencesObject'
5 |
6 | export const preferencesState = atom({
7 | key: 'PreferencesState',
8 | default: initPreferencesObject(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/recoil/atoms/sessionAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/sessionAtoms.ts
2 | import { atom } from 'recoil'
3 |
4 | export const sessionState = atom({
5 | key: 'SessionState',
6 | default: '',
7 | })
8 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/recoil/atoms/toastAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/toastAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initEmptyToast } from '../../model'
5 |
6 | export const toastState = atom({
7 | key: 'ToastState',
8 | default: initEmptyToast(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/recoil/atoms/userAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/userAtoms.ts
2 | import { atom } from 'recoil'
3 | import { initUser } from '../../model'
4 |
5 | export const userState = atom({
6 | key: 'UserState',
7 | default: initUser(),
8 | })
9 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch6/exercise-6-3/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch7/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/.DS_Store
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-1/.DS_Store
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/config.json:
--------------------------------------------------------------------------------
1 | { "version": "v0.6.6" }
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/logs/server-error.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-1/logs/server-error.log
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/models/database.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Elad Elrom, All Rights Reserved.
3 | * Code licensed under the BSD License:
4 | * @author Elad Elrom
5 | */
6 |
7 | // models/database.js
8 |
9 | let usersSchema = {
10 | username: 'String',
11 | email: 'String',
12 | passwordHash: 'String',
13 | passwordSalt: 'String',
14 | lastLoginDate: 'String',
15 | attempt: 'Number',
16 | signDate: 'String',
17 | emailEachLogin: 'Boolean',
18 | loginToken: 'String',
19 | phone: 'String'
20 | };
21 |
22 | if (typeof exports != 'undefined' ) {
23 | exports.usersSchema = usersSchema;
24 | }
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/roomsdb-local.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "db-config",
3 | "version": "1.0",
4 | "environment": {
5 | "host":"localhost",
6 | "user":"myuser",
7 | "password":"YOUR_PASSWORD",
8 | "dsn": "YourSite"
9 | }
10 | }
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/roomsdb.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "db-config",
3 | "version": "1.0",
4 | "environment": {
5 | "host":"SOME_IP_ADDRESS:27017",
6 | "user":"SOME_USER",
7 | "password":"YOUR_PASSWORD",
8 | "dsn": ""
9 | }
10 | }
--------------------------------------------------------------------------------
/Ch7/exercise-7-1/utils/log.js:
--------------------------------------------------------------------------------
1 | function isLocalHost() {
2 | let os = require('os');
3 | return ( os.hostname().indexOf('185.203.171.57') > -1 || os.hostname().toString().indexOf('MacBook') > -1 );
4 | }
5 |
6 | let url = !(isLocalHost) ? '/home/ubuntu/www/logs' : 'logs';
7 | const winston = require('winston');
8 | const logger = winston.createLogger({
9 | level: 'debug',
10 | format: winston.format.json(),
11 | transports: [
12 | new winston.transports.File({ filename: url + '/server-error.log', level: 'error' }),
13 | new winston.transports.File({ filename: url + '/server.log' })
14 | ]
15 | });
16 | logger.add(new winston.transports.Console());
17 |
18 | if (typeof exports !== 'undefined' ) {
19 | exports.logger = logger;
20 | exports.isLocalHost = isLocalHost;
21 | }
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-2/.DS_Store
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-2/public/favicon.ico
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-2/public/logo192.png
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-2/public/logo512.png
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch7/exercise-7-2/src/.DS_Store
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | padding-top: 120px;
4 | height: 350px;
5 | }
6 |
7 | .App-logo {
8 | height: 40vmin;
9 | pointer-events: none;
10 | }
11 |
12 | @media (prefers-reduced-motion: no-preference) {
13 | .App-logo {
14 | animation: App-logo-spin infinite 20s linear;
15 | }
16 | }
17 |
18 | .App-header {
19 | background-color: #282c34;
20 | min-height: 100vh;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | font-size: calc(10px + 2vmin);
26 | color: white;
27 | }
28 |
29 | .App-link {
30 | color: #61dafb;
31 | }
32 |
33 | @keyframes App-logo-spin {
34 | from {
35 | transform: rotate(0deg);
36 | }
37 | to {
38 | transform: rotate(360deg);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | // src/App.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import App from './App'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
17 | /*
18 | Update this file once it's changed. For instance to check if a component you added
19 | include in App.tsx;
20 |
21 | import { shallow } from "enzyme";
22 | import Calculator from "./components/SomeComponent/SomeComponent";
23 |
24 | test('should render SomeComponent', () => {
25 | const wrapper = shallow();
26 | const calculator = wrapper.find(SomeComponent);
27 | expect(calculator.exists()).toBe(true);
28 | })
29 | */
30 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 | /*
6 | import { useSetRecoilState } from 'recoil'
7 | import { toastState } from './recoil/atoms/toastAtoms'
8 | import { initToast, notificationTypesEnums, randomToastId } from './model'
9 | */
10 |
11 | function App() {
12 | // const setToastState = useSetRecoilState(toastState)
13 | // setToastState(initToast(randomToastId(), notificationTypesEnums.Success, 'Hello World'))
14 | return (
15 |
18 | )
19 | }
20 |
21 | export default App
22 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/AppRouter.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | width: 100%;
3 | position: fixed;
4 | bottom: 0%;
5 | }
6 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 | import React from 'react'
3 | import { shallow } from 'enzyme'
4 | import AppRouter from './AppRouter'
5 |
6 | describe('', () => {
7 | let component
8 |
9 | beforeEach(() => {
10 | component = shallow()
11 | })
12 |
13 | test('renders without crashing', () => {
14 | expect(component.length).toBe(1)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/assets/toast/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/assets/toast/error.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/assets/toast/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/components/Login/LoginForm.styles.ts:
--------------------------------------------------------------------------------
1 | // src/components/Login/LoginForm.styles.ts
2 |
3 | import { createStyles, Theme } from '@material-ui/core/styles'
4 |
5 | export default (theme: Theme) =>
6 | createStyles({
7 | container: {
8 | display: 'flex',
9 | flexDirection: 'column',
10 | justifyContent: 'center',
11 | },
12 | })
13 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/components/Register/RegisterForm.styles.ts:
--------------------------------------------------------------------------------
1 | // src/components/Register/RegisterForm.styles.ts
2 |
3 | import { createStyles, Theme } from '@material-ui/core/styles'
4 |
5 | export default (theme: Theme) =>
6 | createStyles({
7 | '@global': {
8 | 'body, html, #root': {
9 | width: '100%',
10 | },
11 | },
12 | container: {
13 | display: 'flex',
14 | flexDirection: 'column',
15 | justifyContent: 'center',
16 | },
17 | })
18 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/components/Toast/ToastNotification.scss:
--------------------------------------------------------------------------------
1 | .toast-buttons {
2 | display: flex;
3 | }
4 |
5 | .toast-buttons button {
6 | color: white;
7 | font-size: 14px;
8 | font-weight: bold;
9 | width: 100px;
10 | height: 50px;
11 | margin: 0 10px;
12 | border: none;
13 | outline: none;
14 | }
15 |
16 | .select {
17 | display: flex;
18 | width: 30%;
19 | margin-top: 10px;
20 | }
21 |
22 | .position-select {
23 | background-color: inherit;
24 | color: #fff;
25 | width: 100%;
26 | height: 30px;
27 | font-size: 16px;
28 | }
29 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/components/UserButton/UserButton.scss:
--------------------------------------------------------------------------------
1 | .MemberButton {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
4 | -webkit-font-smoothing: antialiased;
5 | -moz-osx-font-smoothing: grayscale;
6 | padding-top: 120px;
7 | }
8 |
9 | .dark {
10 | color: white;
11 | background-color: #2b2b2b;
12 | }
13 |
14 | .light {
15 | color: black;
16 | background-color: darkgrey;
17 | }
18 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Centered/Centered.styles.ts:
--------------------------------------------------------------------------------
1 | // src/layout/Centered/Centered.styles.ts
2 |
3 | import { createStyles, Theme } from '@material-ui/core/styles'
4 |
5 | export default (theme: Theme) =>
6 | createStyles({
7 | '@global': {
8 | 'body, html, #root': {
9 | paddingTop: 40,
10 | width: '100%',
11 | },
12 | },
13 | container: {
14 | maxWidth: '400px',
15 | margin: '0 auto',
16 | },
17 | })
18 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Centered/Centered.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: src/layout/Centered/Centered.tsx
6 | */
7 |
8 | import * as React from 'react'
9 | import { withStyles, WithStyles } from '@material-ui/core/styles'
10 | import styles from './Centered.styles'
11 |
12 | const CenteredViewInner: React.FunctionComponent = (props) => {props.children}
13 |
14 | interface Props extends WithStyles {}
15 |
16 | export const Centered = withStyles(styles)(CenteredViewInner)
17 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Centered/index.ts:
--------------------------------------------------------------------------------
1 | // src/layout/index.ts
2 | export { Centered } from './Centered'
3 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .Footer {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Footer/Footer.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Footer from './Footer'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Footer/FooterTheme.tsx:
--------------------------------------------------------------------------------
1 | // src/layout/Footer/FooterTheme.tsx
2 |
3 | import React, { FunctionComponent } from 'react'
4 | import { useRecoilState } from 'recoil'
5 | import FooterComponent from './Footer'
6 |
7 | import { preferencesState } from '../../recoil/atoms/preferencesAtoms'
8 |
9 | export const FooterTheme: FunctionComponent = () => {
10 | const [preferences] = useRecoilState(preferencesState)
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Header/Header.scss:
--------------------------------------------------------------------------------
1 | .Header {
2 | font-family: 'Open Sans', sans-serif;
3 | font-weight: 700;
4 | }
5 |
6 | .NavLinkItem {
7 | color: black;
8 | max-width: 360px;
9 | text-decoration: none;
10 | }
11 |
12 | .NavLinkItem-selected nav {
13 | background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
14 | }
15 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/Header/Header.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import Header from './Header'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | })
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/model/index.ts:
--------------------------------------------------------------------------------
1 | // src/model/index.ts
2 | export * from './preferencesObject'
3 | export * from './toastObject'
4 | export * from './userObject'
5 | export * from './registerObject'
6 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/model/preferencesObject.ts:
--------------------------------------------------------------------------------
1 | // src/model/preferencesObject.ts
2 |
3 | export enum ThemeEnum {
4 | Dark = 'dark',
5 | Light = 'light',
6 | }
7 | // eslint-disable-next-line @typescript-eslint/naming-convention
8 | export interface preferencesObject {
9 | theme: ThemeEnum
10 | }
11 |
12 | export const initPreferencesObject = (): preferencesObject => ({
13 | theme: ThemeEnum.Light,
14 | })
15 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/model/registerObject.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/naming-convention
2 | export interface registerObject {
3 | username: string
4 | email: string
5 | password: string
6 | repeat_password: string
7 | }
8 |
9 | export const initRegister = (): registerObject => ({
10 | username: '',
11 | email: '',
12 | password: '',
13 | repeat_password: '',
14 | })
15 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/model/userObject.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/naming-convention
2 | export interface userObject {
3 | email: string
4 | password: string
5 | }
6 |
7 | export const initUser = (): userObject => ({
8 | email: '',
9 | password: '',
10 | })
11 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/ArticlesPage/ArticlesPage.scss:
--------------------------------------------------------------------------------
1 | .ArticlesPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/BooksPage/BooksPage.scss:
--------------------------------------------------------------------------------
1 | .BooksPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/BuildSiteCoursePage/BuildSiteCoursePage.scss:
--------------------------------------------------------------------------------
1 | .BuildSiteCoursePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/CoachingHourlyPage/CoachingHourlyPage.scss:
--------------------------------------------------------------------------------
1 | .CoachingHourlyPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/CoachingPackagePage/CoachingPackagePage.scss:
--------------------------------------------------------------------------------
1 | .CoachingPackagePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/ContactPage/ContactPage.scss:
--------------------------------------------------------------------------------
1 | .ContactPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/HomePage/HomePage.scss:
--------------------------------------------------------------------------------
1 | .HomePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/LoginPage/LoginPage.scss:
--------------------------------------------------------------------------------
1 | .LoginPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/MembersPage/MembersPage.scss:
--------------------------------------------------------------------------------
1 | .MembersPage {
2 | padding-left: 20px;
3 | padding-bottom: 200px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/NotFoundPage/NotFoundPage.scss:
--------------------------------------------------------------------------------
1 | .NotFoundPage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/RegisterPage/RegisterPage.scss:
--------------------------------------------------------------------------------
1 | .RegisterPage {
2 | padding-bottom: 350px;
3 | }
4 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/pages/YouBuildMySitePage/YouBuildMySitePage.scss:
--------------------------------------------------------------------------------
1 | .YouBuildMySitePage {
2 | padding-top: 120px;
3 | padding-left: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/preferencesAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/preferencesAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initPreferencesObject } from '../../model/preferencesObject'
5 |
6 | export const preferencesState = atom({
7 | key: 'PreferencesState',
8 | default: initPreferencesObject(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/registerAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/regsiterAtoms.ts
2 | import { atom } from 'recoil'
3 | import { initRegister } from '../../model'
4 |
5 | export const registerState = atom({
6 | key: 'RegisterState',
7 | default: initRegister(),
8 | })
9 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/sessionAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/sessionAtoms.ts
2 | import { atom } from 'recoil'
3 |
4 | export const sessionState = atom({
5 | key: 'SessionState',
6 | default: '',
7 | })
8 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/toastAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/toastAtoms.ts
2 |
3 | import { atom } from 'recoil'
4 | import { initEmptyToast } from '../../model'
5 |
6 | export const toastState = atom({
7 | key: 'ToastState',
8 | default: initEmptyToast(),
9 | })
10 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/recoil/atoms/userAtoms.ts:
--------------------------------------------------------------------------------
1 | // src/recoil/atoms/userAtoms.ts
2 | import { atom } from 'recoil'
3 | import { initUser } from '../../model'
4 |
5 | export const userState = atom({
6 | key: 'UserState',
7 | default: initUser(),
8 | })
9 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/templates/component/component.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | Author: Eli Elad Elrom
3 | Website: https://EliElrom.com
4 | License: MIT License
5 | Component: TemplateName.tsx
6 | */
7 |
8 | import React from 'react'
9 | import './TemplateName.scss'
10 |
11 | export default class TemplateName extends React.PureComponent {
12 | constructor(props: ITemplateNameProps) {
13 | super(props)
14 | this.state = {}
15 | }
16 |
17 | render() {
18 | return (
19 | <>>
20 | )
21 | }
22 | }
23 |
24 | interface ITemplateNameProps {
25 | // TODO
26 | }
27 |
28 | interface ITemplateNameState {
29 | // TODO
30 | }
31 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch7/exercise-7-2/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch8/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch8/.DS_Store
--------------------------------------------------------------------------------
/Ch8/app/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch8/app/.DS_Store
--------------------------------------------------------------------------------
/Ch9/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/.DS_Store
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*
2 | public/*
3 | docs/*
4 | templates/*
5 | src/react-app-env.d.ts
6 | src/serviceWorker.ts
7 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/.gitignore:
--------------------------------------------------------------------------------
1 | # misc
2 | .DS_Store
3 | package-lock.json
4 | yarn-error.log
5 | yarn.lock
6 | docs
7 |
8 | # IDE
9 | .idea
10 |
11 | # dependencies
12 | /node_modules
13 |
14 | # dependencies
15 | /node_modules
16 | /.pnp
17 | .pnp.js
18 |
19 | # testing
20 | /coverage
21 |
22 | # production
23 | /build
24 |
25 | # misc
26 | .DS_Store
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | npm-debug.log*
33 | yarn-debug.log*
34 | yarn-error.log*
35 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "printWidth": 100,
4 | "semi": false,
5 | "singleQuote": true,
6 | "tabWidth": 2
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/e2e/global.d.ts:
--------------------------------------------------------------------------------
1 | // globals defined in jest.config.js need to be included in this `d.ts`
2 | // file to avoid TS lint errors
3 | declare let SERVER_URL: string
4 | declare let JEST_TIMEOUT: number
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'jest-puppeteer',
3 | globals: {
4 | SERVER_URL: 'http://localhost:3000',
5 | JEST_TIMEOUT: 30000
6 | },
7 | testRegex: './*\\.test\\.tsx$'
8 | }
9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE')
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/jest-puppeteer.config.js:
--------------------------------------------------------------------------------
1 | // jest-puppeteer.config.js
2 | module.exports = {
3 | server: {
4 | command: `yarn start`,
5 | port: 3000,
6 | launchTimeout: 20000,
7 | debug: true,
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/calculator-input.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/hello-jest-enzyme-ts/public/calculator-input.jpg
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/calculator.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/hello-jest-enzyme-ts/public/calculator.jpg
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/hello-jest-enzyme-ts/public/favicon.ico
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/hello-jest-enzyme-ts/public/logo192.png
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch9/hello-jest-enzyme-ts/public/logo512.png
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/App.tsx:
--------------------------------------------------------------------------------
1 | // src/App.tsx
2 |
3 | import React from 'react'
4 | import './App.scss'
5 | import Calculator from './components/Calculator/Calculator'
6 |
7 | function App() {
8 | return (
9 |
10 |
11 |
12 | )
13 | }
14 |
15 | export default App
16 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/AppRouter.test.tsx:
--------------------------------------------------------------------------------
1 | // src/AppRouter.test.tsx
2 |
3 | import React from 'react'
4 | import { shallow } from 'enzyme'
5 | import AppRouter from './AppRouter'
6 |
7 | describe('', () => {
8 | let component
9 |
10 | beforeEach(() => {
11 | component = shallow()
12 | })
13 |
14 | test('renders without crashing', () => {
15 | expect(component.length).toBe(1)
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/assets/README:
--------------------------------------------------------------------------------
1 | Break down your assets by names: about, home, etc.
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/components/Calculator/Calculator.scss:
--------------------------------------------------------------------------------
1 | .calculator-output {
2 | background: url('/calculator-input.jpg') no-repeat right top;
3 | color: #fff;
4 | font-size: 50px;
5 | width: 464px;
6 | height: 120px;
7 | text-align: center;
8 | display: flex;
9 | justify-content: center;
10 | align-items: center;
11 | }
12 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/components/README:
--------------------------------------------------------------------------------
1 | components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component UserButton
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/features/README:
--------------------------------------------------------------------------------
1 | features components goes here.
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/index.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | }
8 |
9 | code {
10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
11 | }
12 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/layout/README:
--------------------------------------------------------------------------------
1 | layout components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component BoxLayout --type=layout
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/model/README:
--------------------------------------------------------------------------------
1 | place all your object model files here, for example: userObject.ts
2 |
3 | export interface userObject {
4 | email: string
5 | password: string
6 | }
7 |
8 | export const initUser = (): userObject => ({
9 | email: '',
10 | password: '',
11 | })
12 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/pages/README:
--------------------------------------------------------------------------------
1 | Pages components goes here, you can generate with generate-react-cli, example;
2 | $ npx generate-react-cli component HomePage --type=page
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/recoil/atoms/README:
--------------------------------------------------------------------------------
1 | Recoil atoms goes here, example: userAtoms.ts;
2 |
3 | // src/recoil/atoms/userAtoms.ts
4 | import { atom } from 'recoil'
5 | import { initUser } from '../../model'
6 |
7 | export const userState = atom({
8 | key: 'UserState',
9 | default: initUser(),
10 | })
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | // src/redux/store.ts
2 |
3 | import { configureStore, combineReducers } from '@reduxjs/toolkit'
4 |
5 | const store = configureStore({
6 | reducer: combineReducers({
7 | // your reducers goes here
8 | }),
9 | })
10 |
11 | export default store
12 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect'
6 |
7 | import { configure } from 'enzyme'
8 | import Adapter from 'enzyme-adapter-react-16'
9 |
10 | configure({ adapter: new Adapter() })
11 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/templates/component/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/templates/component/test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import TemplateName from './TemplateName';
4 |
5 | describe('', () => {
6 | let component;
7 |
8 | beforeEach(() => {
9 | component = shallow();
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/templates/component/test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { shallow } from 'enzyme'
3 | import TemplateName from './TemplateName'
4 |
5 | describe('', () => {
6 | let component
7 |
8 | beforeEach(() => {
9 | component = shallow()
10 | });
11 |
12 | test('It should mount', () => {
13 | expect(component.length).toBe(1)
14 | })
15 | })
16 |
--------------------------------------------------------------------------------
/Ch9/hello-jest-enzyme-ts/templates/page/style.scss:
--------------------------------------------------------------------------------
1 | .TemplateName {
2 | }
--------------------------------------------------------------------------------
/Contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Apress Source Code
2 |
3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers.
4 |
5 | ## How to Contribute
6 |
7 | 1. Make sure you have a GitHub account.
8 | 2. Fork the repository for the relevant book.
9 | 3. Create a new branch on which to make your change, e.g.
10 | `git checkout -b my_code_contribution`
11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted.
12 | 5. Submit a pull request.
13 |
14 | Thank you for your contribution!
--------------------------------------------------------------------------------