Skip to content

Commit 3df3038

Browse files
committed
add configuration files; make better test example
1 parent f8c9e7d commit 3df3038

9 files changed

Lines changed: 310 additions & 49 deletions

File tree

.eslintrc

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{
2+
"extends": [
3+
"airbnb-base",
4+
"plugin:@typescript-eslint/recommended",
5+
"plugin:prettier/recommended",
6+
"prettier"
7+
],
8+
"plugins": [
9+
"filenames",
10+
"functional"
11+
],
12+
"parser": "@typescript-eslint/parser",
13+
"globals": {
14+
"document": false,
15+
"window": false,
16+
"Event": false,
17+
"CustomEvent": false,
18+
"FormData": false,
19+
"fetch": false,
20+
"DOMParser": false,
21+
"FileReader": false,
22+
"requestAnimationFrame": false,
23+
"Element": false
24+
},
25+
"rules": {
26+
"curly": ["error", "all"],
27+
"@typescript-eslint/explicit-member-accessibility": ["error",
28+
{ "accessibility": "no-public" }
29+
],
30+
"no-new": 0,
31+
"no-unused-vars": "off",
32+
"@typescript-eslint/no-unused-vars": ["error", {
33+
"vars": "all",
34+
"args": "after-used",
35+
"ignoreRestSiblings": false
36+
}],
37+
"no-underscore-dangle": "off",
38+
"@typescript-eslint/explicit-function-return-type": "off",
39+
"@typescript-eslint/no-non-null-assertion": 2,
40+
"no-restricted-syntax": [
41+
"error",
42+
{
43+
"selector": "ForInStatement",
44+
"message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
45+
},
46+
{
47+
"selector": "LabeledStatement",
48+
"message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
49+
},
50+
{
51+
"selector": "WithStatement",
52+
"message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
53+
},
54+
{
55+
"selector": "TSEnumDeclaration",
56+
"message": "Don't declare enums, use a discriminated union instead: https://github.com/typescript-eslint/typescript-eslint/issues/561#issue-448808322"
57+
}
58+
],
59+
"filenames/match-exported": 2,
60+
"no-use-before-define": "off",
61+
"@typescript-eslint/explicit-module-boundary-types": "off",
62+
"no-unused-expressions": "off",
63+
"@typescript-eslint/no-unused-expressions": ["error"],
64+
"@typescript-eslint/naming-convention": [
65+
"error",
66+
{
67+
"selector": "variableLike",
68+
"format": ["camelCase", "PascalCase"]
69+
},
70+
{
71+
"selector": "class",
72+
"format": ["PascalCase"]
73+
}
74+
],
75+
"@typescript-eslint/consistent-type-assertions": [
76+
"error",
77+
{ "assertionStyle": "never" }
78+
],
79+
"prettier/prettier": ["error", {
80+
"printWidth": 140,
81+
"endOfLine": "auto"
82+
}],
83+
"@typescript-eslint/no-explicit-any": "error",
84+
"import/extensions": [
85+
"error",
86+
"ignorePackages",
87+
{
88+
"js": "never",
89+
"jsx": "never",
90+
"ts": "never",
91+
"tsx": "never"
92+
}
93+
],
94+
"import/no-extraneous-dependencies": ["error", {
95+
"devDependencies": [
96+
"**/__mocks__/**/*",
97+
"gulpfile.ts",
98+
"**/*.test.ts",
99+
"**/*.test.tsx",
100+
"webpack.config.js"
101+
]
102+
}
103+
],
104+
"class-methods-use-this": "off"
105+
},
106+
"ignorePatterns": ["output", "dist", "node_modules"],
107+
"settings": {
108+
"import/resolver": {
109+
"node": {
110+
"extensions": [".js", ".jsx", ".ts", ".tsx"]
111+
},
112+
"alias": {
113+
"map": [
114+
["~", "./src"]
115+
],
116+
"extensions": [".ts", ".js", ".jsx", ".json", ".tsx"]
117+
}
118+
}
119+
},
120+
"overrides": [
121+
{
122+
"files": ["*.tsx", "*.ts"],
123+
"rules": {
124+
"react/prop-types": "off",
125+
"import/no-unresolved": [2, {
126+
"ignore": ["StoreTypes", "react-hook-form"]
127+
}],
128+
"@typescript-eslint/explicit-module-boundary-types": "off",
129+
"no-redeclare": "off",
130+
"no-shadow": "off",
131+
"no-unused-expressions": "off",
132+
"@typescript-eslint/no-unused-expressions": ["error"]
133+
}
134+
},
135+
{
136+
"files": ["**/*test.ts", "*.test.tsx", "*.test.jsx", "*.test.js", "**/__mocks__/**/*", "**/__tests__/**/*"],
137+
"rules": {
138+
"max-classes-per-file": "off",
139+
"filenames/match-exported": "off"
140+
},
141+
"globals": {
142+
"expect": false,
143+
"test": false,
144+
"jest": false,
145+
"jsdom": false,
146+
"describe": false,
147+
"it": false,
148+
"beforeEach": false,
149+
"afterEach": false,
150+
"afterAll": false
151+
}
152+
},
153+
{
154+
"files": ["*.js", "*.ts"],
155+
"rules": {
156+
"linebreak-style": 0
157+
}
158+
},
159+
{
160+
"files": ["*.js", "*.jsx"],
161+
"rules": {
162+
"@typescript-eslint/no-var-requires": "off"
163+
}
164+
}
165+
]
166+
}

.vscode/default.code-workspace

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"folders": [
3+
{
4+
"path": ".."
5+
}
6+
],
7+
"settings": {
8+
"files.eol": "\n",
9+
"editor.tabSize": 2,
10+
"editor.insertSpaces": true,
11+
"eslint.validate": [
12+
"typescript"
13+
],
14+
"search.exclude": {
15+
"**/node_modules": true,
16+
"**/bower_components": true,
17+
"**/*.code-search": true,
18+
"**/output": true
19+
}
20+
}
21+
}

.vscode/extensions.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"recommendations": [
3+
"dbaeumer.vscode-eslint",
4+
"orta.vscode-jest"
5+
]
6+
}

.vscode/settings.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"editor.codeActionsOnSave": {
3+
"source.fixAll.eslint": true,
4+
"source.fixAll": false
5+
},
6+
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
7+
"editor.formatOnSave": true,
8+
"editor.tabSize": 2,
9+
"editor.detectIndentation": false,
10+
"editor.rulers": [
11+
80,
12+
],
13+
"explorer.fileNesting.enabled": true,
14+
"explorer.fileNesting.patterns": {
15+
"package.json": "babel.config.js, webpack.config.js, .clark-certs.pem, .depcheckrc.yml, .eslintrc, .npmrc, yarn.lock, tsconfig.json, .prettierrc.yml, .iyarc",
16+
"*.ts": "${basename}.test.ts, I${basename}.ts",
17+
"*.tsx": "${basename}.test.tsx, I${basename}.tsx",
18+
"task.json": "taskTransform.js"
19+
}
20+
}

package-lock.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dependencies": {
66
"@emotion/react": "^11.11.1",
77
"@emotion/styled": "^11.11.0",
8+
"@faker-js/faker": "^8.3.1",
89
"@fontsource/roboto": "^5.0.4",
910
"@mui/icons-material": "^5.13.7",
1011
"@mui/lab": "^5.0.0-alpha.135",

proxy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ app.use(
1414
// supabase studio
1515
app.use(createProxyMiddleware(['/project', '/monaco-editor', '/css', '/_next', '/api', '/favicon', '/img'], { target: 'http://192.168.1.50:3000', changeOrigin: true, ws: true }));
1616

17-
app.use(createProxyMiddleware('/', { target: 'http://localhost:8443', changeOrigin: true, ws: true }));
17+
app.use(createProxyMiddleware('/', { target: 'http://localhost:443', changeOrigin: true, ws: true }));
1818

1919
app.listen(3000);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { min } from 'lodash';
2+
import { validateEmail } from './validateEmail';
3+
import { faker } from '@faker-js/faker';
4+
5+
describe('when email is valid', () => {
6+
const validEmails = [
7+
'example@example.com',
8+
'firstname.lastname@example.com',
9+
'email@subdomain.example.com',
10+
'firstname+lastname@example.com',
11+
'1234567890@example.com',
12+
'email@example-one.com',
13+
'_______@example.com',
14+
'email@example.co.jp',
15+
'firstname-lastname@example.com'
16+
];
17+
18+
validEmails.forEach(email => {
19+
it(`should return true for ${email}`, () => {
20+
expect(validateEmail(email)).toBe(true);
21+
});
22+
});
23+
24+
test('should handle emails with long local part', () => {
25+
const longLocalPartEmail = 'a'.repeat(faker.number.int({min: 65, max: 256})) + '@example.com';
26+
expect(validateEmail(longLocalPartEmail)).toBe(false);
27+
});
28+
29+
test('should handle emails with long domain part', () => {
30+
const longDomainPartEmail = 'example@' + 'a'.repeat(faker.number.int({min: 65, max: 200})) + '.com';
31+
expect(validateEmail(longDomainPartEmail)).toBe(false);
32+
});
33+
34+
});
35+
36+
describe('when email is invalid', () => {
37+
const invalidEmails = [
38+
'plainaddress',
39+
'@no-local-part.com',
40+
'Outlook Contact <outlook-contact@domain.com>',
41+
'no-at-sign.net',
42+
'no-tld@domain',
43+
';beginning-semicolon@semicolon.com',
44+
'middle-semicolon@domain.co;m',
45+
'trailing-semicolon@domain.com;',
46+
'"email"@example.com',
47+
'email@domain@domain.com',
48+
'.email@domain.com',
49+
'email.@domain.com',
50+
'email..email@domain.com',
51+
'あいうえお@example.com',
52+
'email@domain.com (Joe Smith)',
53+
'email@domain',
54+
'email@-domain.com',
55+
'email@111.222.333.44444',
56+
'email@domain..com'
57+
];
58+
59+
invalidEmails.forEach((email) => {
60+
it(`should return false for ${email}`, () => {
61+
expect(validateEmail(email)).toBe(false);
62+
});
63+
})
64+
65+
test('should return false for empty string', () => {
66+
expect(validateEmail('')).toBe(false);
67+
});
68+
69+
test('should return false for null or undefined', () => {
70+
expect(validateEmail(null)).toBe(false);
71+
expect(validateEmail(undefined)).toBe(false);
72+
});
73+
74+
});

0 commit comments

Comments
 (0)