test: init

This commit is contained in:
Ibrahima G. Coulibaly
2024-06-22 03:29:34 +01:00
parent b6ae7c5cdf
commit 8d0ea995bf
8 changed files with 178 additions and 64 deletions

46
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: CI
on:
push:
branches:
- main # or the branch you want to trigger the workflow on
pull_request:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18' # Specify the Node.js version you want to use
- name: Install dependencies
run: npm install
- name: Run tests
run: npm run test
- name: Build project
run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v1.2
with:
publish-dir: ./build
production-branch: main
deploy-message: Deploy from GitHub Actions
enable-pull-request-comment: true
enable-commit-comment: true
overwrites-pull-request-comment: true
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
timeout-minutes: 1

View File

@@ -20,7 +20,8 @@
"test:ui": "vitest --ui",
"lint": "eslint src --max-warnings=0",
"typecheck": "tsc --project tsconfig.json --noEmit",
"prepare": "husky install"
"prepare": "husky install",
"prebuild": "npm run test"
},
"dependencies": {
"@emotion/react": "^11.11.4",

View File

@@ -1,32 +0,0 @@
import { render, screen } from '@testing-library/react'
import App from './App'
describe('<App />', () => {
it('should render the App', () => {
const { container } = render(<App />)
expect(
screen.getByRole('heading', {
name: /Welcome!/i,
level: 1
})
).toBeInTheDocument()
expect(
screen.getByText(
/This is a boilerplate build with Vite, React 18, TypeScript, Vitest, Testing Library, TailwindCSS 3, Eslint and Prettier./i
)
).toBeInTheDocument()
expect(
screen.getByRole('link', {
name: /start building for free/i
})
).toBeInTheDocument()
expect(screen.getByRole('img')).toBeInTheDocument()
expect(container.firstChild).toBeInTheDocument()
})
})

View File

@@ -1,4 +1,4 @@
export {default as useDebounce} from "./useDebounce";
export {default as useTimeout} from "./useTimeout";
export {default as usePrevious} from "./usePrevious";
export {default as useUpdateEffect} from "./useUpdateEffect";
export { default as useDebounce } from './useDebounce';
export { default as useTimeout } from './useTimeout';
export { default as usePrevious } from './usePrevious';
export { default as useUpdateEffect } from './useUpdateEffect';

View File

@@ -9,10 +9,9 @@ import ToolTextResult from '../../../components/result/ToolTextResult';
import { Field, Formik, FormikProps, useFormikContext } from 'formik';
import * as Yup from 'yup';
import ToolOptions from '../../../components/ToolOptions';
import { splitIntoChunks, splitTextByLength } from './service';
import { compute, SplitOperatorType } from './service';
import { CustomSnackBarContext } from '../../../contexts/CustomSnackBarContext';
type SplitOperatorType = 'symbol' | 'regex' | 'length' | 'chunks';
const initialValues = {
splitSeparatorType: 'symbol' as SplitOperatorType,
symbolValue: ' ',
@@ -160,24 +159,20 @@ export default function SplitText() {
regexValue,
lengthValue
} = values;
let splitText;
switch (splitSeparatorType) {
case 'symbol':
splitText = input.split(symbolValue);
break;
case 'regex':
splitText = input.split(new RegExp(regexValue));
break;
case 'length':
splitText = splitTextByLength(input, Number(lengthValue));
break;
case 'chunks':
splitText = splitIntoChunks(input, Number(chunksValue)).map(
(chunk) => `${charBeforeChunk}${chunk}${charAfterChunk}`
);
}
const res = splitText.join(outputSeparator);
setResult(res);
setResult(
compute(
splitSeparatorType,
input,
symbolValue,
regexValue,
Number(lengthValue),
Number(chunksValue),
charBeforeChunk,
charAfterChunk,
outputSeparator
)
);
} catch (exception: unknown) {
if (exception instanceof Error)
showSnackBar(exception.message, 'error');

View File

@@ -1,4 +1,6 @@
export function splitTextByLength(text: string, length: number) {
export type SplitOperatorType = 'symbol' | 'regex' | 'length' | 'chunks';
function splitTextByLength(text: string, length: number) {
if (length <= 0) throw new Error('Length must be a positive number');
const result: string[] = [];
for (let i = 0; i < text.length; i += length) {
@@ -7,7 +9,7 @@ export function splitTextByLength(text: string, length: number) {
return result;
}
export function splitIntoChunks(text: string, numChunks: number) {
function splitIntoChunks(text: string, numChunks: number) {
if (numChunks <= 0)
throw new Error('Number of chunks must be a positive number');
const totalLength = text.length;
@@ -31,3 +33,33 @@ export function splitIntoChunks(text: string, numChunks: number) {
return result;
}
export function compute(
splitSeparatorType: SplitOperatorType,
input: string,
symbolValue: string,
regexValue: string,
lengthValue: number,
chunksValue: number,
charBeforeChunk: string,
charAfterChunk: string,
outputSeparator: string
) {
let splitText;
switch (splitSeparatorType) {
case 'symbol':
splitText = input.split(symbolValue);
break;
case 'regex':
splitText = input.split(new RegExp(regexValue));
break;
case 'length':
splitText = splitTextByLength(input, lengthValue);
break;
case 'chunks':
splitText = splitIntoChunks(input, chunksValue).map(
(chunk) => `${charBeforeChunk}${chunk}${charAfterChunk}`
);
}
return splitText.join(outputSeparator);
}

View File

@@ -0,0 +1,72 @@
import { describe, it, expect } from 'vitest';
import { compute } from './service';
describe('compute function', () => {
it('should split by symbol', () => {
const result = compute('symbol', 'hello world', ' ', '', 0, 0, '', '', ',');
expect(result).toBe('hello,world');
});
it('should split by regex', () => {
const result = compute(
'regex',
'hello1world2again',
'',
'\\d',
0,
0,
'',
'',
','
);
expect(result).toBe('hello,world,again');
});
it('should split by length', () => {
const result = compute('length', 'helloworld', '', '', 3, 0, '', '', ',');
expect(result).toBe('hel,low,orl,d');
});
it('should split into chunks', () => {
const result = compute(
'chunks',
'helloworldagain',
'',
'',
0,
3,
'[',
']',
','
);
expect(result).toBe('[hello],[world],[again]');
});
it('should handle empty input', () => {
const result = compute('symbol', '', ' ', '', 0, 0, '', '', ',');
expect(result).toBe('');
});
it('should handle length greater than text length', () => {
const result = compute('length', 'hi', '', '', 5, 0, '', '', ',');
expect(result).toBe('hi');
});
it('should handle chunks greater than text length', () => {
expect(() => {
compute('chunks', 'hi', '', '', 0, 5, '', '', ',');
}).toThrow('Text length must be at least as long as the number of chunks');
});
it('should handle invalid length', () => {
expect(() => {
compute('length', 'hello', '', '', -1, 0, '', '', ',');
}).toThrow('Length must be a positive number');
});
it('should handle invalid chunks', () => {
expect(() => {
compute('chunks', 'hello', '', '', 0, 0, '', '', ',');
}).toThrow('Number of chunks must be a positive number');
});
});

View File

@@ -1,7 +1,7 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import tsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';
// https://vitejs.dev/config https://vitest.dev/config
export default defineConfig({
@@ -10,6 +10,6 @@ export default defineConfig({
globals: true,
environment: 'happy-dom',
setupFiles: '.vitest/setup',
include: ['**/test.{ts,tsx}']
include: ['**/*.test.{ts,tsx}']
}
})
});