Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ test-temp-*
test-results/
fixtures-test/
.rslib/

!packages/core/src/coverage
7 changes: 6 additions & 1 deletion examples/node/rstest.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { defineConfig } from '@rstest/core';

export default defineConfig({});
export default defineConfig({
coverage: {
enabled: true,
provider: 'istanbul',
},
});
36 changes: 36 additions & 0 deletions examples/node/src/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const removeDuplicates = <T>(arr: T[]): T[] => {
return [...new Set(arr)];
};

export const chunk = <T>(arr: T[], size: number): T[][] => {
if (size <= 0) {
throw new Error('Chunk size must be greater than 0');
}
const result: T[][] = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
};

export const flatten = <T>(arr: (T | T[])[]): T[] => {
return arr.reduce<T[]>((acc, val) => {
return acc.concat(Array.isArray(val) ? flatten(val) : val);
}, []);
};

export const findMax = (arr: number[]): number => {
if (arr.length === 0) {
throw new Error('Array cannot be empty');
}
return Math.max(...arr);
};

export const shuffle = <T>(arr: T[]): T[] => {
const shuffled = [...arr];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
};
30 changes: 30 additions & 0 deletions examples/node/src/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const formatDate = (date: Date, format = 'YYYY-MM-DD'): string => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');

return format
.replace('YYYY', year.toString())
.replace('MM', month)
.replace('DD', day);
};

export const addDays = (date: Date, days: number): Date => {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
};

export const getDaysBetween = (date1: Date, date2: Date): number => {
const timeDiff = Math.abs(date2.getTime() - date1.getTime());
return Math.ceil(timeDiff / (1000 * 3600 * 24));
};

export const isWeekend = (date: Date): boolean => {
const day = date.getDay();
return day === 0 || day === 6; // Sunday = 0, Saturday = 6
};

export const getQuarter = (date: Date): number => {
return Math.floor((date.getMonth() + 3) / 3);
};
25 changes: 25 additions & 0 deletions examples/node/src/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const capitalize = (str: string): string => {
if (!str) return str;
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};

export const reverseString = (str: string): string => {
return str.split('').reverse().join('');
};

export const isPalindrome = (str: string): boolean => {
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return cleaned === cleaned.split('').reverse().join('');
};

export const countWords = (str: string): number => {
return str
.trim()
.split(/\s+/)
.filter((word) => word.length > 0).length;
};

export const truncate = (str: string, maxLength: number): string => {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength - 3) + '...';
};
78 changes: 78 additions & 0 deletions examples/node/test/array.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { describe, expect, it } from '@rstest/core';
import {
chunk,
findMax,
flatten,
removeDuplicates,
shuffle,
} from '../src/array';

describe('Array Utils', () => {
describe('removeDuplicates', () => {
it('should remove duplicate numbers', () => {
expect(removeDuplicates([1, 2, 2, 3, 3, 4])).toEqual([1, 2, 3, 4]);
});

it('should remove duplicate strings', () => {
expect(removeDuplicates(['a', 'b', 'b', 'c'])).toEqual(['a', 'b', 'c']);
});

it('should handle empty array', () => {
expect(removeDuplicates([])).toEqual([]);
});
});

describe('chunk', () => {
it('should chunk array into specified size', () => {
expect(chunk([1, 2, 3, 4, 5, 6], 2)).toEqual([
[1, 2],
[3, 4],
[5, 6],
]);
});

it('should handle remainder elements', () => {
expect(chunk([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]);
});

it('should throw error for invalid chunk size', () => {
expect(() => chunk([1, 2, 3], 0)).toThrow(
'Chunk size must be greater than 0',
);
});
});

describe('flatten', () => {
it('should flatten nested arrays', () => {
expect(flatten([1, [2, 3], [4, [5, 6]]])).toEqual([1, 2, 3, 4, 5, 6]);
});

it('should handle empty arrays', () => {
expect(flatten([])).toEqual([]);
});
});

describe('findMax', () => {
it('should find maximum number', () => {
expect(findMax([1, 5, 3, 9, 2])).toBe(9);
});

it('should throw error for empty array', () => {
expect(() => findMax([])).toThrow('Array cannot be empty');
});
});

describe('shuffle', () => {
it('should return array with same length', () => {
const original = [1, 2, 3, 4, 5];
const shuffled = shuffle(original);
expect(shuffled).toHaveLength(original.length);
});

it('should contain all original elements', () => {
const original = [1, 2, 3, 4, 5];
const shuffled = shuffle(original);
expect(shuffled.sort()).toEqual(original.sort());
});
});
});
76 changes: 76 additions & 0 deletions examples/node/test/date.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { describe, expect, it } from '@rstest/core';
import {
addDays,
formatDate,
getDaysBetween,
getQuarter,
isWeekend,
} from '../src/date';

describe('Date Utils', () => {
describe('formatDate', () => {
it('should format date with default format', () => {
const date = new Date('2023-12-25');
expect(formatDate(date)).toBe('2023-12-25');
});

it('should format date with custom format', () => {
const date = new Date('2023-12-25');
expect(formatDate(date, 'DD/MM/YYYY')).toBe('25/12/2023');
});
});

describe('addDays', () => {
it('should add days to date', () => {
const date = new Date('2023-12-25');
const result = addDays(date, 5);
expect(result.getDate()).toBe(30);
});

it('should subtract days from date', () => {
const date = new Date('2023-12-25');
const result = addDays(date, -5);
expect(result.getDate()).toBe(20);
});
});

describe('getDaysBetween', () => {
it('should calculate days between two dates', () => {
const date1 = new Date('2023-12-25');
const date2 = new Date('2023-12-30');
expect(getDaysBetween(date1, date2)).toBe(5);
});

it('should handle reversed dates', () => {
const date1 = new Date('2023-12-30');
const date2 = new Date('2023-12-25');
expect(getDaysBetween(date1, date2)).toBe(5);
});
});

describe('isWeekend', () => {
it('should return true for Saturday', () => {
const saturday = new Date('2023-12-23'); // Saturday
expect(isWeekend(saturday)).toBe(true);
});

it('should return true for Sunday', () => {
const sunday = new Date('2023-12-24'); // Sunday
expect(isWeekend(sunday)).toBe(true);
});

it('should return false for weekday', () => {
const monday = new Date('2023-12-25'); // Monday
expect(isWeekend(monday)).toBe(false);
});
});

describe('getQuarter', () => {
it('should return correct quarter for different months', () => {
expect(getQuarter(new Date('2023-01-15'))).toBe(1);
expect(getQuarter(new Date('2023-04-15'))).toBe(2);
expect(getQuarter(new Date('2023-07-15'))).toBe(3);
expect(getQuarter(new Date('2023-10-15'))).toBe(4);
});
});
});
88 changes: 88 additions & 0 deletions examples/node/test/string.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { describe, expect, it } from '@rstest/core';
import {
capitalize,
countWords,
isPalindrome,
reverseString,
truncate,
} from '../src/string';

describe('String Utils', () => {
describe('capitalize', () => {
it('should capitalize first letter', () => {
expect(capitalize('hello')).toBe('Hello');
});

it('should handle empty string', () => {
expect(capitalize('')).toBe('');
});

it('should handle single character', () => {
expect(capitalize('a')).toBe('A');
});
});

describe('reverseString', () => {
it('should reverse string', () => {
expect(reverseString('hello')).toBe('olleh');
});

it('should handle empty string', () => {
expect(reverseString('')).toBe('');
});

it('should handle palindrome', () => {
expect(reverseString('racecar')).toBe('racecar');
});
});

describe('isPalindrome', () => {
it('should return true for palindrome', () => {
expect(isPalindrome('racecar')).toBe(true);
});

it('should return true for palindrome with spaces', () => {
expect(isPalindrome('A man a plan a canal Panama')).toBe(true);
});

it('should return false for non-palindrome', () => {
expect(isPalindrome('hello')).toBe(false);
});

it('should handle empty string', () => {
expect(isPalindrome('')).toBe(true);
});
});

describe('countWords', () => {
it('should count words correctly', () => {
expect(countWords('hello world')).toBe(2);
});

it('should handle multiple spaces', () => {
expect(countWords('hello world test')).toBe(3);
});

it('should handle empty string', () => {
expect(countWords('')).toBe(0);
});

it('should handle single word', () => {
expect(countWords('hello')).toBe(1);
});
});

describe('truncate', () => {
it('should truncate long string', () => {
expect(truncate('This is a very long string', 10)).toBe('This is...');
});

it('should not truncate short string', () => {
expect(truncate('Short', 10)).toBe('Short');
});

it('should handle exact length', () => {
expect(truncate('Exactly10!', 10)).toBe('Exactly10!');
});
});
});
11 changes: 11 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@
"@vitest/snapshot": "^3.2.4",
"birpc": "2.4.0",
"chai": "^5.2.1",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-instrument": "^6.0.3",
"istanbul-lib-report": "^3.0.1",
"istanbul-lib-source-maps": "^5.0.6",
"istanbul-reports": "^3.1.7",
"pathe": "^2.0.3",
"std-env": "^3.9.0",
"swc-plugin-coverage-instrument": "^0.0.28",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builtin istanbul coverage directly into Rstest is too heavy. Rstest can provide a separate package for users to install as needed. When users set provider: 'istanbul', rstest can import the relevant transform plugin and provider from @rstest/coverage-istanbul.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

"tinypool": "^1.1.1"
},
"devDependencies": {
Expand All @@ -72,6 +78,11 @@
"@rstest/tsconfig": "workspace:*",
"@sinonjs/fake-timers": "^14.0.0",
"@types/babel__code-frame": "^7.0.6",
"@types/istanbul-lib-coverage": "^2.0.6",
"@types/istanbul-lib-instrument": "^1.7.7",
"@types/istanbul-lib-report": "^3.0.3",
"@types/istanbul-lib-source-maps": "^4.0.4",
"@types/istanbul-reports": "^3.0.4",
"@types/jsdom": "^21.1.7",
"@types/sinonjs__fake-timers": "^8.1.5",
"@types/source-map-support": "^0.5.10",
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ const createDefaultConfig = (): NormalizedConfig => ({
maxConcurrency: 5,
printConsoleTrace: false,
disableConsoleIntercept: false,
coverage: {
enabled: false,
},
});

export const withDefaultConfig = (config: RstestConfig): NormalizedConfig => {
Expand Down
Loading
Loading