chore: remove jest -> cypress for unit tests
This commit is contained in:
@ -0,0 +1,18 @@
|
||||
import { isStringWithOnlyOneEmoji } from '../../../../components/Emoji/isStringWithOnlyOneEmoji'
|
||||
|
||||
describe('components/Emoji/isStringWithOnlyOneEmoji', () => {
|
||||
it('returns true with a string with only one emoji', () => {
|
||||
expect(isStringWithOnlyOneEmoji(':wave:')).equal(true)
|
||||
expect(isStringWithOnlyOneEmoji(':smile:')).equal(true)
|
||||
})
|
||||
|
||||
it('returns false with a string with multiple emoji or with text', () => {
|
||||
expect(isStringWithOnlyOneEmoji(':wave: :smile:')).equal(false)
|
||||
expect(isStringWithOnlyOneEmoji(':wave: some text')).equal(false)
|
||||
expect(isStringWithOnlyOneEmoji('some text :wave:')).equal(false)
|
||||
})
|
||||
|
||||
it('returns false with a string without emoji', () => {
|
||||
expect(isStringWithOnlyOneEmoji('some text')).equal(false)
|
||||
})
|
||||
})
|
16
cypress/component/components/Footer.cy.tsx
Normal file
16
cypress/component/components/Footer.cy.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Footer } from '../../../components/Footer'
|
||||
|
||||
describe('<Footer />', () => {
|
||||
it('should render with appropriate link tag version', () => {
|
||||
const version = '1.0.0'
|
||||
cy.mount(<Footer version={version} />)
|
||||
cy.contains('Thream')
|
||||
.get('[data-cy=version-link-website]')
|
||||
.should('have.text', `website v${version}`)
|
||||
.should(
|
||||
'have.attr',
|
||||
'href',
|
||||
`https://github.com/Thream/website/releases/tag/v${version}`
|
||||
)
|
||||
})
|
||||
})
|
35
cypress/component/components/design/FormState.cy.tsx
Normal file
35
cypress/component/components/design/FormState.cy.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { FormState } from '../../../../components/design/FormState'
|
||||
|
||||
describe('<FormState />', () => {
|
||||
it('should return nothing if the state is idle', () => {
|
||||
cy.mount(<FormState state='idle' />)
|
||||
.get('[data-cy-root]')
|
||||
.should('be.empty')
|
||||
})
|
||||
|
||||
it('should return nothing if the message is null', () => {
|
||||
cy.mount(<FormState state='error' />)
|
||||
.get('[data-cy-root]')
|
||||
.should('be.empty')
|
||||
})
|
||||
|
||||
it('should render the <Loader /> if state is loading', () => {
|
||||
cy.mount(<FormState state='loading' />)
|
||||
.get('[data-cy=loader]')
|
||||
.should('be.visible')
|
||||
})
|
||||
|
||||
it('should render the success message if state is success', () => {
|
||||
const message = 'Success Message'
|
||||
cy.mount(<FormState state='success' message={message} id='success' />)
|
||||
.get('#success')
|
||||
.contains(message)
|
||||
})
|
||||
|
||||
it('should render the error message if state is error', () => {
|
||||
const message = 'Error Message'
|
||||
cy.mount(<FormState state='error' message={message} id='error' />)
|
||||
.get('#error')
|
||||
.contains(message)
|
||||
})
|
||||
})
|
48
cypress/component/components/design/Input.cy.tsx
Normal file
48
cypress/component/components/design/Input.cy.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { Input, getInputType } from '../../../../components/design/Input'
|
||||
|
||||
describe('<Input />', () => {
|
||||
it('should render the label', () => {
|
||||
const labelContent = 'label content'
|
||||
cy.mount(<Input label={labelContent} />)
|
||||
.get('label')
|
||||
.should('have.text', labelContent)
|
||||
})
|
||||
|
||||
it('should not render forgot password link', () => {
|
||||
cy.mount(<Input type='text' label='content' showForgotPassword />)
|
||||
.get('[data-cy=forgot-password-link]')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('should render forgot password link', () => {
|
||||
cy.mount(<Input type='password' label='content' showForgotPassword />)
|
||||
.get('[data-cy=forgot-password-link]')
|
||||
.should('exist')
|
||||
})
|
||||
|
||||
it('should not render the eye icon if the input is not of type "password"', () => {
|
||||
cy.mount(<Input type='text' label='content' />)
|
||||
.get('[data-cy=password-eye]')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('should handlePassword with eye icon', async () => {
|
||||
cy.mount(<Input type='password' label='content' />)
|
||||
.get('input')
|
||||
.should('have.attr', 'type', 'password')
|
||||
.get('[data-cy=password-eye]')
|
||||
.click()
|
||||
.get('input')
|
||||
.should('have.attr', 'type', 'text')
|
||||
})
|
||||
|
||||
describe('getInputType', () => {
|
||||
it('should return `text`', () => {
|
||||
expect(getInputType('password')).equal('text')
|
||||
})
|
||||
|
||||
it('should return `password`', () => {
|
||||
expect(getInputType('text')).equal('password')
|
||||
})
|
||||
})
|
||||
})
|
71
cypress/component/hooks/useForm/getErrorTranslationKey.cy.ts
Normal file
71
cypress/component/hooks/useForm/getErrorTranslationKey.cy.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import type { ErrorObject } from 'ajv'
|
||||
|
||||
import { getErrorTranslationKey } from '../../../../hooks/useForm/getErrorTranslationKey'
|
||||
|
||||
const errorObject: ErrorObject = {
|
||||
instancePath: '/path',
|
||||
keyword: 'keyword',
|
||||
params: {},
|
||||
schemaPath: '/path'
|
||||
}
|
||||
|
||||
describe('hooks/useForm/getErrorTranslationKey', () => {
|
||||
it('returns `errors:invalid` with unknown keyword', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'unknownkeyword'
|
||||
})
|
||||
).equal('errors:invalid')
|
||||
})
|
||||
|
||||
it('returns `errors:invalid` with format != email', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'format',
|
||||
params: { format: 'email' }
|
||||
})
|
||||
).equal('errors:email')
|
||||
})
|
||||
|
||||
it('returns `errors:email` with format = email', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'format',
|
||||
params: { format: 'email' }
|
||||
})
|
||||
).equal('errors:email')
|
||||
})
|
||||
|
||||
it('returns `errors:required` with minLength and limit = 1', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'minLength',
|
||||
params: { limit: 1 }
|
||||
})
|
||||
).equal('errors:required')
|
||||
})
|
||||
|
||||
it('returns `errors:minLength` with minLength and limit > 1', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'minLength',
|
||||
params: { limit: 5 }
|
||||
})
|
||||
).equal('errors:minLength')
|
||||
})
|
||||
|
||||
it('returns `errors:maxLength` with maxLength', () => {
|
||||
expect(
|
||||
getErrorTranslationKey({
|
||||
...errorObject,
|
||||
keyword: 'maxLength',
|
||||
params: { limit: 5 }
|
||||
})
|
||||
).equal('errors:maxLength')
|
||||
})
|
||||
})
|
22
cypress/component/hooks/useForm/handleCheckboxBoolean.cy.ts
Normal file
22
cypress/component/hooks/useForm/handleCheckboxBoolean.cy.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Type } from '@sinclair/typebox'
|
||||
|
||||
import { handleCheckboxBoolean } from '../../../../hooks/useForm/handleCheckboxBoolean'
|
||||
|
||||
const schema = Type.Object({
|
||||
myBoolean: Type.Boolean(),
|
||||
myString: Type.String()
|
||||
})
|
||||
|
||||
describe('hooks/useForm/handleCheckboxBoolean', () => {
|
||||
it('should convert all checkbox property to boolean', () => {
|
||||
const object = {
|
||||
myBoolean: 'on',
|
||||
myString: 'on'
|
||||
}
|
||||
const result = handleCheckboxBoolean(object, schema)
|
||||
expect(result).deep.equal({
|
||||
myBoolean: true,
|
||||
myString: 'on'
|
||||
})
|
||||
})
|
||||
})
|
@ -0,0 +1,20 @@
|
||||
import { replaceEmptyStringInObjectToNull } from '../../../../hooks/useForm/replaceEmptyStringInObjectToNull'
|
||||
|
||||
describe('hooks/useForm/replaceEmptyStringInObjectToNull', () => {
|
||||
it('should replace empty string in object to null except for required properties', () => {
|
||||
expect(
|
||||
replaceEmptyStringInObjectToNull(
|
||||
{
|
||||
foo: '',
|
||||
bar: 'bar',
|
||||
baz: ''
|
||||
},
|
||||
['baz']
|
||||
)
|
||||
).deep.equal({
|
||||
foo: null,
|
||||
bar: 'bar',
|
||||
baz: ''
|
||||
})
|
||||
})
|
||||
})
|
10
cypress/component/tools/utils/capitalize.cy.ts
Normal file
10
cypress/component/tools/utils/capitalize.cy.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { capitalize } from '../../../../tools/utils/capitalize'
|
||||
|
||||
describe('tools/utils/capitalize', () => {
|
||||
it('should capitalize the first letter of a string', () => {
|
||||
expect(capitalize('hello')).equal('Hello')
|
||||
expect(capitalize('HeLlo')).equal('HeLlo')
|
||||
expect(capitalize('member(s)')).equal('Member(s)')
|
||||
expect(capitalize('Member(s)')).equal('Member(s)')
|
||||
})
|
||||
})
|
@ -49,3 +49,5 @@ describe('Common > Header', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -45,3 +45,5 @@ describe('Common > application/authentication', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -7,3 +7,5 @@ describe('Page > /404', () => {
|
||||
cy.get('[data-cy=status-code]').contains('404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -7,3 +7,5 @@ describe('Page > /500', () => {
|
||||
cy.get('[data-cy=status-code]').contains('500')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -267,3 +267,5 @@ describe('Pages > /application/[guildId]/[channelId]', () => {
|
||||
.should('eq', '/404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -132,3 +132,5 @@ describe('Pages > /application/[guildId]/[channelId]/settings', () => {
|
||||
.should('eq', '/404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -72,3 +72,5 @@ describe('Pages > /application/[guildId]/channels/create', () => {
|
||||
.should('eq', '/404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -102,3 +102,5 @@ describe('Pages > /application/[guildId]/settings', () => {
|
||||
.should('eq', '/404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -42,3 +42,5 @@ describe('Pages > /application/guilds/create', () => {
|
||||
cy.get('#message').should('have.text', 'Error: Internal Server Error.')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -75,6 +75,8 @@ describe('Pages > /application/guilds/join', () => {
|
||||
)
|
||||
cy.visit('/application/guilds/join')
|
||||
cy.get('.guilds-public-list').children().should('have.length', 1)
|
||||
cy.get('[data-testid=progress-spinner]').should('be.visible')
|
||||
cy.get('[data-cy=progress-spinner]').should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -30,3 +30,5 @@ describe('Pages > /application', () => {
|
||||
.should('eq', '/application/guilds/join')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -33,3 +33,5 @@ describe('Pages > /application/users/[userId]', () => {
|
||||
.should('eq', '/404')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -35,3 +35,5 @@ describe('Pages > /authentication/forgot-password', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -46,3 +46,5 @@ describe('Pages > /authentication/reset-password', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -53,3 +53,5 @@ describe('Pages > /authentication/signin', () => {
|
||||
cy.get('#error-password').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -83,3 +83,5 @@ describe('Pages > /authentication/signup', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -10,3 +10,5 @@ describe('Page > /', () => {
|
||||
.should('eq', '/authentication/signup')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
@ -1,66 +0,0 @@
|
||||
import path from 'node:path'
|
||||
|
||||
import { getLocal } from 'mockttp'
|
||||
|
||||
import { API_DEFAULT_PORT } from '../../tools/api'
|
||||
|
||||
/// <reference types="cypress" />
|
||||
|
||||
/**
|
||||
* @typedef {import('../fixtures/handler').Method} Method
|
||||
*/
|
||||
|
||||
/** @type {import('mockttp').Mockttp | null} */
|
||||
let server = null
|
||||
|
||||
const UPLOADS_FIXTURES_DIRECTORY = path.join(
|
||||
process.cwd(),
|
||||
'cypress',
|
||||
'fixtures',
|
||||
'uploads'
|
||||
)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
on('task', {
|
||||
/**
|
||||
* @param {import('../fixtures/handler').Handlers} handlers
|
||||
*/
|
||||
async startMockServer(handlers) {
|
||||
server = getLocal({
|
||||
cors: true
|
||||
})
|
||||
await server.start(API_DEFAULT_PORT)
|
||||
for (const handler of handlers) {
|
||||
const { isFile = false } = handler.response
|
||||
const method = /** @type {Lowercase<Method>} */ (
|
||||
handler.method.toLowerCase()
|
||||
)
|
||||
if (isFile) {
|
||||
await server[method](handler.url).thenFromFile(
|
||||
handler.response.statusCode,
|
||||
path.join(UPLOADS_FIXTURES_DIRECTORY, ...handler.response.body)
|
||||
)
|
||||
} else {
|
||||
await server[method](handler.url).thenJson(
|
||||
handler.response.statusCode,
|
||||
handler.response.body
|
||||
)
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
async stopMockServer() {
|
||||
if (server != null) {
|
||||
await server.stop()
|
||||
server = null
|
||||
}
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
3
cypress/support/commands.ts
Normal file
3
cypress/support/commands.ts
Normal file
@ -0,0 +1,3 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
export {}
|
14
cypress/support/component-index.html
Normal file
14
cypress/support/component-index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<title>Components App</title>
|
||||
<!-- Used by Next.js to inject CSS. -->
|
||||
<div id="__next_css__DO_NOT_USE__"></div>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
14
cypress/support/component.ts
Normal file
14
cypress/support/component.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { mount } from 'cypress/react'
|
||||
|
||||
import './commands'
|
||||
import '../../styles/global.css'
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
mount: typeof mount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"types": ["cypress"],
|
||||
"isolatedModules": false
|
||||
},
|
||||
"include": ["../node_modules/cypress", "./**/*.ts"]
|
||||
}
|
Reference in New Issue
Block a user