Browse Source

test: 补齐 ESLint+jest 工程化配置,治理 shadowColor 硬编码为 colors.shadow,tsconfig 排除测试目录

master
doublex001 2 months ago
parent
commit
a55799490e
  1. 4
      app/(enterprise)/enterprise-overview.tsx
  2. 2
      app/(tabs)/jobs.tsx
  3. 4
      app/candidate-detail.tsx
  4. 2
      app/interview-score.tsx
  5. 2
      app/job-evaluations.tsx
  6. 2
      app/job-publish.tsx
  7. 6
      babel.config.js
  8. 9
      jest.config.js
  9. 13
      src/__tests__/colors.test.ts
  10. 28
      src/__tests__/constants.test.ts
  11. 35
      src/__tests__/salary.test.ts
  12. 31
      src/__tests__/utils.test.ts
  13. 2
      src/theme/colors.ts
  14. 8
      tsconfig.json
  15. 7321
      yarn.lock

4
app/(enterprise)/enterprise-overview.tsx

@ -245,7 +245,7 @@ const styles = StyleSheet.create({
padding: 16,
backgroundColor: colors.white,
borderRadius: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.06,
shadowRadius: 8,
@ -321,7 +321,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,

2
app/(tabs)/jobs.tsx

@ -451,7 +451,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 14,
marginHorizontal: 8,
marginTop: 4,
shadowColor: '#000000',
shadowColor: colors.shadow,
shadowOpacity: 0.06,
shadowRadius: 8,
shadowOffset: { width: 0, height: 2 },

4
app/candidate-detail.tsx

@ -395,7 +395,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,
@ -512,7 +512,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,

2
app/interview-score.tsx

@ -420,7 +420,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,

2
app/job-evaluations.tsx

@ -500,7 +500,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,

2
app/job-publish.tsx

@ -434,7 +434,7 @@ const styles = StyleSheet.create({
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowColor: colors.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,

6
babel.config.js

@ -0,0 +1,6 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};

9
jest.config.js

@ -0,0 +1,9 @@
module.exports = {
preset: 'jest-expo',
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native|expo(nent)?|@expo(nent)?|expo-|@expo-|@expo/|@react-navigation|react-native-svg|@react-native-async-storage))',
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
testMatch: ['**/__tests__/**/*.(test|spec).(ts|tsx|js)'],
collectCoverageFrom: ['src/**/*.{ts,tsx}', 'app/**/*.{ts,tsx}'],
};

13
src/__tests__/colors.test.ts

@ -0,0 +1,13 @@
import { colors } from '../theme';
describe('设计令牌 colors', () => {
it('主色为品牌蓝 #2C83FD', () => {
expect(colors.primary).toBe('#2C83FD');
});
it('success 为唯一绿色 token #10B981', () => {
expect(colors.success).toBe('#10B981');
});
it('阴影色已收敛到 token,不再硬编码 #000', () => {
expect(colors.shadow).toBe('#000000');
});
});

28
src/__tests__/constants.test.ts

@ -0,0 +1,28 @@
import { JOB_LEVEL_LABEL, SALARY_RANGES, MAX_RETRY_COUNT } from '../constants';
describe('JOB_LEVEL_LABEL', () => {
it('岗位等级映射中文标签', () => {
expect(JOB_LEVEL_LABEL.excellent).toBe('优秀');
expect(JOB_LEVEL_LABEL.good).toBe('良好');
expect(JOB_LEVEL_LABEL.medium).toBe('中等');
});
});
describe('SALARY_RANGES', () => {
it('首项为不限(max 为 Infinity)', () => {
expect(SALARY_RANGES[0]).toEqual({
label: '不限',
min: 0,
max: Number.POSITIVE_INFINITY,
});
});
it('包含 10-20K 区间', () => {
expect(SALARY_RANGES).toContainEqual({ label: '10-20K', min: 10, max: 20 });
});
});
describe('MAX_RETRY_COUNT', () => {
it('请求失败自动重试 3 次', () => {
expect(MAX_RETRY_COUNT).toBe(3);
});
});

35
src/__tests__/salary.test.ts

@ -0,0 +1,35 @@
import { computeSalaryResult } from '../api/api';
describe('computeSalaryResult(薪资计算器业务规则)', () => {
it('低薪且五险一金+起征点覆盖时个税为 0', () => {
const input = {
monthlyGross: 5000,
bonusMonths: 0,
socialBase: 5000,
providentFundRate: 0.12,
specialDeduction: 0,
};
const r = computeSalaryResult(input as any);
// monthlySocial = 5000*(0.08+0.02+0.005+0.12) = 1125
expect(r.monthlySocial).toBe(1125);
// taxable = max(0, 5000-1125-5000) = 0 → 个税 0
expect(r.monthlyTax).toBe(0);
// monthlyNet = 5000 - 1125 = 3875
expect(r.monthlyNet).toBe(3875);
expect(r.annualGross).toBe(60000);
expect(r.annualNet).toBe(46500);
});
it('含年终奖时月度税前合计摊入', () => {
const input = {
monthlyGross: 10000,
bonusMonths: 2,
socialBase: 10000,
providentFundRate: 0.12,
specialDeduction: 0,
};
const r = computeSalaryResult(input as any);
// monthlyTotal = 10000 * (1 + 2/12) = 11666.67 → 四舍五入 11667
expect(r.monthlyTotal).toBe(11667);
});
});

31
src/__tests__/utils.test.ts

@ -0,0 +1,31 @@
import { formatThousands, formatCurrency, formatViews } from '../utils';
describe('formatThousands', () => {
it('千分位格式化 12846 → "12,846"', () => {
expect(formatThousands(12846)).toBe('12,846');
});
it('不足千位原样返回', () => {
expect(formatThousands(123)).toBe('123');
});
});
describe('formatCurrency', () => {
it('默认 0 位小数 30000 → "30,000"', () => {
expect(formatCurrency(30000)).toBe('30,000');
});
it('指定 2 位小数补齐', () => {
expect(formatCurrency(12345.6, 2)).toBe('12,345.60');
});
});
describe('formatViews', () => {
it('≥1万 → 万单位', () => {
expect(formatViews(23000)).toBe('2.3万');
});
it('整万去掉 .0', () => {
expect(formatViews(20000)).toBe('2万');
});
it('<1万返回原数字', () => {
expect(formatViews(8500)).toBe('8500');
});
});

2
src/theme/colors.ts

@ -109,6 +109,7 @@ export const colors = {
textPrimary: '#2C3E50',
/** 深色底上的反白文字 */
textInverse: '#FFFFFF',
shadow: '#000000',
/** 焦点环色 · 键盘聚焦指示器(WCAG 2.4.11) */
focusRing: '#1F6FDB',
/** 弹层遮罩 · 半透明黑(Modal / 底部弹层背景) */
@ -172,6 +173,7 @@ export const darkColors = {
textSecondary: '#91A0B3',
textPrimary: '#E6EDF3',
textInverse: '#0E1116',
shadow: '#000000',
focusRing: '#5399FD',
} as const;

8
tsconfig.json

@ -9,5 +9,13 @@
"include": [
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules",
".expo",
"coverage",
"__tests__",
"**/*.test.ts",
"**/*.test.tsx"
]
}

7321
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save