├── .babelrc ├── .eslintrc.json ├── next-env.d.ts ├── public ├── favicon.ico ├── favicon-32x32.png ├── icon-remove.svg ├── images │ ├── bg-header-mobile.svg │ └── bg-header-desktop.svg ├── zeit.svg └── logos │ ├── faceit.svg │ ├── the-air-filter-company.svg │ ├── myhome.svg │ ├── shortly.svg │ ├── eyecam-co.svg │ ├── account.svg │ ├── insure.svg │ ├── manage.svg │ ├── photosnap.svg │ └── loop-studios.svg ├── styles ├── index.scss ├── _mixin.scss ├── _variables.scss ├── global.scss └── shared.scss ├── declaration.d.ts ├── config └── jest │ └── cssTransform.js ├── components ├── header.tsx ├── filter.tsx └── jobItem.tsx ├── pages ├── _app.js └── index.tsx ├── __tests__ ├── snapshot.js ├── testing-library.js └── __snapshots__ │ └── snapshot.js.snap ├── setupTests.js ├── types └── types.ts ├── next.config.js ├── README.md ├── .gitignore ├── jest.config.js ├── tsconfig.json ├── package.json └── mock └── jobs.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potentialdev-web/next-typescript-sass/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /styles/index.scss: -------------------------------------------------------------------------------- 1 | @import "./variables"; 2 | @import "./mixin"; 3 | @import "./global"; 4 | @import "./shared"; -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/potentialdev-web/next-typescript-sass/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.scss' { 2 | const content: {[className: string]: string}; 3 | export default content; 4 | } -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | process() { 3 | return 'module.exports = {};' 4 | }, 5 | getCacheKey() { 6 | return 'cssTransform' 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /styles/_mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin display-flex($direction, $justify, $align) { 2 | display: flex; 3 | flex-direction: $direction; 4 | justify-content: $justify; 5 | align-items: $align; 6 | } -------------------------------------------------------------------------------- /components/header.tsx: -------------------------------------------------------------------------------- 1 | const Header = ({...rest}) => { 2 | return ( 3 |
7 | ); 8 | } 9 | 10 | export default Header; 11 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/index.scss' 2 | 3 | // This default export is required in a new `pages/_app.js` file. 4 | export default function MyApp({ Component, pageProps }) { 5 | return 6 | } 7 | -------------------------------------------------------------------------------- /public/icon-remove.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__tests__/snapshot.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import Index from '../pages/index' 4 | 5 | it('renders homepage unchanged', () => { 6 | const tree = renderer.create().toJSON() 7 | expect(tree).toMatchSnapshot() 8 | }) 9 | -------------------------------------------------------------------------------- /setupTests.js: -------------------------------------------------------------------------------- 1 | // optional: configure or set up a testing framework before each test 2 | // if you delete this file, remove `setupFilesAfterEnv` from `jest.config.js` 3 | 4 | // used for __tests__/testing-library.js 5 | // learn more: https://github.com/testing-library/jest-dom 6 | import '@testing-library/jest-dom/extend-expect' 7 | -------------------------------------------------------------------------------- /types/types.ts: -------------------------------------------------------------------------------- 1 | export interface JobType { 2 | featured: boolean, 3 | logo?: string, 4 | company?: string, 5 | new?: boolean, 6 | position?: string, 7 | postedAt?: string, 8 | contract?: string, 9 | location?: string, 10 | role?: string, 11 | level?: string, 12 | tools?: string[], 13 | languages?: string[], 14 | } 15 | -------------------------------------------------------------------------------- /__tests__/testing-library.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from '@testing-library/react' 3 | import Index from '../pages/index' 4 | 5 | test('renders deploy link', () => { 6 | const { getByText } = render() 7 | const linkElement = getByText( 8 | /Instantly deploy your Next\.js site to a public URL with Vercel\./ 9 | ) 10 | expect(linkElement).toBeInTheDocument() 11 | }) 12 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withSass = require('@zeit/next-sass'); 2 | const withCSS = require("@zeit/next-css"); 3 | 4 | module.exports = withCSS(withSass({ 5 | webpack (config, options) { 6 | config.module.rules.push({ 7 | test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, 8 | use: { 9 | loader: 'url-loader', 10 | options: { 11 | limit: 100000 12 | } 13 | } 14 | }); 15 | 16 | return config; 17 | } 18 | })); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js + Jest 2 | 3 | This example shows how to configure Jest to work with Next.js. 4 | 5 | This includes Next.js' built-in support for Global CSS, CSS Modules, and TypeScript! 6 | 7 | ## How to Use 8 | 9 | Quickly get started using [Create Next App](https://github.com/vercel/next.js/tree/canary/packages/create-next-app#readme)! 10 | 11 | In your terminal, run the following command: 12 | 13 | ```bash 14 | npx create-next-app --example with-jest 15 | ``` 16 | 17 | ## Run Jest Tests 18 | 19 | ```bash 20 | npm test 21 | ``` 22 | -------------------------------------------------------------------------------- /.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 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /public/images/bg-header-mobile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverageFrom: [ 3 | '**/*.{js,jsx,ts,tsx}', 4 | '!**/*.d.ts', 5 | '!**/node_modules/**', 6 | ], 7 | setupFilesAfterEnv: ['/setupTests.js'], 8 | testPathIgnorePatterns: ['/node_modules/', '/.next/'], 9 | transform: { 10 | '^.+\\.(js|jsx|ts|tsx)$': '/node_modules/babel-jest', 11 | '^.+\\.css$': '/config/jest/cssTransform.js', 12 | }, 13 | transformIgnorePatterns: [ 14 | '/node_modules/', 15 | '^.+\\.module\\.(css|sass|scss)$', 16 | ], 17 | moduleNameMapper: { 18 | '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy', 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "jsx": "preserve" 20 | }, 21 | "include": [ 22 | "next-env.d.ts", 23 | "**/*.ts", 24 | "**/*.tsx" 25 | ], 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /public/zeit.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /styles/_variables.scss: -------------------------------------------------------------------------------- 1 | // dimension 2 | $xl: 1200px; 3 | $xd: 992px; 4 | $md: 768px; 5 | $sm: 576px; 6 | $xs: 375px; 7 | 8 | // font 9 | $font: 'Spartan', sans-serif; 10 | 11 | $weights: ( 12 | 'medium': 500, 13 | 'semi-bold': 700, 14 | ); 15 | 16 | @each $name, $weight in $weights { 17 | .font-#{$name} { 18 | font-weight: $weight; 19 | } 20 | } 21 | 22 | $sizes: ( 23 | 'normal': 14, 24 | 'big': 18, 25 | ); 26 | 27 | @each $name, $size in $sizes { 28 | .fontsize-#{$name} { 29 | font-size: $size + px; 30 | } 31 | } 32 | 33 | // colors 34 | $white: #fff; 35 | $black: #2f3837; 36 | $green: #5da4a8; 37 | $bg-light-grayish-cyan: hsl(180, 52%, 96%); //background 38 | $light-grayish-cyan: hsl(180, 31%, 95%); // (Filter Tablets) 39 | $dark-grayish-cyan: hsl(180, 8%, 52%); 40 | $very-dark-grayish-cyan: hsl(180, 14%, 20%); 41 | 42 | :export { 43 | green: $green; 44 | backgroundColor: $bg-light-grayish-cyan; 45 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-jest", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start", 8 | "export": "npm run build && next export", 9 | "test": "jest --watch", 10 | "test:ci": "jest --ci" 11 | }, 12 | "dependencies": { 13 | "@zeit/next-sass": "^1.0.1", 14 | "next": "latest", 15 | "node-sass": "^4.14.1", 16 | "react": "16.12.0", 17 | "react-dom": "16.12.0", 18 | "react-select": "^3.1.0" 19 | }, 20 | "devDependencies": { 21 | "@testing-library/jest-dom": "^5.1.0", 22 | "@testing-library/react": "^9.4.0", 23 | "@types/node": "^14.6.3", 24 | "@types/react": "^16.9.49", 25 | "babel-jest": "^25.5.1", 26 | "identity-obj-proxy": "^3.0.0", 27 | "jest": "^25.5.4", 28 | "react-test-renderer": "^16.12.0", 29 | "typescript": "^4.0.2", 30 | "url-loader": "^4.1.0" 31 | }, 32 | "license": "MIT" 33 | } 34 | -------------------------------------------------------------------------------- /public/images/bg-header-desktop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/logos/faceit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/global.scss: -------------------------------------------------------------------------------- 1 | html { 2 | background: $bg-light-grayish-cyan; 3 | } 4 | 5 | body { 6 | font-family: $font; 7 | margin: 0; 8 | width: 100%; 9 | overflow-x: hidden; 10 | } 11 | 12 | p, ul { 13 | display: inline; 14 | margin-block-start: 0; 15 | margin-block-end: 0; 16 | margin-inline-start: 0; 17 | margin-inline-end: 0; 18 | padding-inline-start: 0; 19 | } 20 | 21 | ul { 22 | li { 23 | list-style-type: none; 24 | } 25 | } 26 | 27 | main { 28 | display: flex; 29 | justify-content: center; 30 | } 31 | 32 | .header { 33 | width: 100%; 34 | height: 140px; 35 | background: url('~/images/bg-header-desktop.svg') no-repeat; 36 | background-size: cover; 37 | 38 | @media (max-width: $sm) { 39 | background: url('~/images/bg-header-mobile.svg') no-repeat; 40 | background-size: cover; 41 | } 42 | } 43 | 44 | .container { 45 | margin-top: -32px; 46 | 47 | @media (min-width: $xl) { 48 | padding: 0 30px; 49 | width: $xl; 50 | } 51 | 52 | @media screen and (max-width: $xl - 1) and (min-width: $xs - 1) { 53 | width: 90%; 54 | } 55 | 56 | @media (max-width: $xs) { 57 | padding: 0 20px; 58 | max-width: $xs; 59 | } 60 | } -------------------------------------------------------------------------------- /public/logos/the-air-filter-company.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/logos/myhome.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/snapshot.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders homepage unchanged 1`] = ` 4 | 76 | `; 77 | -------------------------------------------------------------------------------- /public/logos/shortly.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/filter.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FC, 3 | } from 'react'; 4 | import 5 | Select, 6 | { components } 7 | from 'react-select'; 8 | import variants from '../styles/_variables.scss'; 9 | 10 | interface FilterProps { 11 | className?: string; 12 | options?: object; 13 | value?: any; 14 | onChange?: any; 15 | } 16 | 17 | const filterStyle = { 18 | control: styles => ({ 19 | ...styles, 20 | backgroundColor: 'white', 21 | minHeight: 65, 22 | marginBottom: 45, 23 | borderRadius: 5, 24 | border: 'none', 25 | boxShadow: '0px 20px 21px #d4e9ec' 26 | }), 27 | valueContainer: (styles) => ({ 28 | ...styles, 29 | padding: '10px 30px' 30 | }), 31 | multiValue: (styles) => ({ 32 | ...styles, 33 | color: variants.green, 34 | backgroundColor: variants.backgroundColor, 35 | margin: '0 7px' 36 | }), 37 | multiValueLabel: (styles, { data }) => ({ 38 | ...styles, 39 | color: variants.green, 40 | fontSize: 14, 41 | fontWeight: 'bold', 42 | padding: '10px 10px', 43 | }), 44 | multiValueRemove: (styles, { data }) => ({ 45 | ...styles, 46 | color: '#fff', 47 | backgroundColor: variants.green, 48 | padding: '5px 10px', 49 | 50 | ':hover': { 51 | backgroundColor: '#000000', 52 | color: 'white', 53 | cursor: 'pointer' 54 | }, 55 | 56 | }), 57 | }; 58 | 59 | const ClearIndicator = props => { 60 | const { 61 | getStyles, 62 | innerProps: { ref, ...restInnerProps }, 63 | } = props; 64 | return ( 65 |
70 | Clear 71 |
72 | ); 73 | }; 74 | 75 | 76 | const Filter: FC = ({ 77 | options, 78 | className, 79 | ...rest 80 | }) => { 81 | return ( 82 |