Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Month 13/step 1 #14

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7b512fa
Добавлено решение с разворотом строки
ulbee May 6, 2023
8a2f1c9
Добавлена задача про последовательность фибоначчи
ulbee May 6, 2023
0bdbb40
Добавлена сортировка пузырьком
ulbee May 6, 2023
0b7ffc9
Добавлена задача про сортировки
ulbee May 7, 2023
ef13f5c
Добавлена задача со стеком
ulbee May 7, 2023
0d66da6
Решение задачи с очередью
ulbee May 7, 2023
b6ed411
Первая версия списка
ulbee May 8, 2023
a57160a
Решение последней задачи про список
ulbee May 8, 2023
a2092f9
Правки по ревью
ulbee May 8, 2023
8d78b0c
Добавлен eslint
ulbee May 17, 2023
aaeef6c
Добавлены все зависимости для написания тестов
ulbee May 17, 2023
ee0ae80
Добавлены юнит-тесты для компонентов button и circle
ulbee May 21, 2023
a7b8572
Добавлены e2e тесты для проверки доступности приложения и роутинга
ulbee May 21, 2023
2a7a3aa
Добавлены e2e тесты для задачи с переворотом строки
ulbee May 21, 2023
d0a0c64
Рефакторинг некоторых тестов
ulbee May 21, 2023
55ef6cd
Рефакторинг для e2e тестов для задачи с разворотом строки
ulbee May 26, 2023
d9bf318
Рефакторинг e2e теста для переворота строки; добавлен e2e тест для по…
ulbee May 28, 2023
f5e90ff
Добавлен e2e тест для стека; мелкие исправления других e2e тестов
ulbee May 28, 2023
a1ab0c0
Добавлен e2e тест для проверки работоспособности очереди; Мелкие испр…
ulbee May 28, 2023
3142062
Первая версия e2e тестов для списка; небольшой рефакторинг e2e тестов…
ulbee May 30, 2023
7ad005d
Добавлены e2e тесты для списка
ulbee May 30, 2023
b46de4a
Мелкие исправления
ulbee May 30, 2023
9ed6443
Алгоритм разворота строки вынесен в отдельный модуль; добавлены юнит-…
ulbee May 30, 2023
45a3852
Добавлены исключения в eslint конфиг; исправлено форматирование в юни…
ulbee May 31, 2023
9533bd0
Алгоритм сортировки пузырьком вынесен в отдельный модуль
ulbee May 31, 2023
b4a1801
Юнит-тесты для сортировки пузырьком
ulbee May 31, 2023
bbf4bf2
Алгоритм сортировки выбором вынесен в отдельный модуль; добавлены юни…
ulbee May 31, 2023
9e497c6
Исправления кодстайла по eslint
ulbee May 31, 2023
bc91d59
Правки по ревью
ulbee May 31, 2023
65c3158
Установлен eslint-plugin-n
ulbee May 31, 2023
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
30 changes: 30 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended",
"standard-with-typescript",
"plugin:cypress/recommended"
],
"overrides": [
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"tsconfigRootDir": "./",
"project": ["./tsconfig.json"]
},
"plugins": [
"react",
"cypress"
],
"ignorePatterns": ["src/components/ui/**", "src/reportWebVitals.ts", "!src/components/ui/button/button.test.js", "!src/components/ui/circle/circle.test.js"],
"rules": {
"@typescript-eslint/strict-boolean-expressions": 0,
"@typescript-eslint/prefer-optional-chain": 0,
"@typescript-eslint/prefer-nullish-coalescing": 0
}
}
17 changes: 17 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from "cypress";

export default defineConfig({
component: {
devServer: {
framework: "create-react-app",
bundler: "webpack",
},
},

e2e: {
baseUrl: "http://localhost:3000/",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
Empty file added cypress/.eslintrc.js
Empty file.
10 changes: 10 additions & 0 deletions cypress/e2e/consts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const inputTextSelector = 'form input[type="text"]'
export const inputNumberSelector = 'form input[type="number"]'
export const submitFormSelector = 'form button[type="submit"]'
export const letterSelector = 'p[class*="letter"]'
export const headSelector = 'div[class*="head"]'
export const tailSelector = 'div[class*="tail"]'
export const formSelector = 'form'

export const SMALL_DELAY = 500
export const DELAY = 1000
35 changes: 35 additions & 0 deletions cypress/e2e/fibonacci.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { fibonacci } from '../../src/utils/fibonacci'
import { submitFormSelector, inputNumberSelector, letterSelector, SMALL_DELAY, formSelector } from './consts'

const N = 10

describe('fibonacci function works correctly', () => {
beforeEach(() => {
cy.visit('fibonacci')
})

it('should be disabled button when there is no number to count', () => {
cy.contains('Рассчитать').should('have.attr', 'disabled')
})

it('should animate couning correct fibonscci number', () => {
cy.get(inputNumberSelector).type(N)
cy.get(submitFormSelector).click()

cy.get(formSelector).next().as('container')

for (let i = 0; i < N + 1; i++) {
cy.get('@container').children('div').eq(i).find(letterSelector).then(($p) => {
const n = $p.text()

if (i === 0 || i === 1) {
expect(n, 'text').to.equal('1')
} else {
expect(n, 'text').to.equal(String(fibonacci(i)))
}
})
}
// eslint-disable-next-line
cy.wait(SMALL_DELAY)
})
})
5 changes: 5 additions & 0 deletions cypress/e2e/is-available.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('service is available', function () {
it('should be available on localhost:3000', function () {
cy.visit('/')
})
})
228 changes: 228 additions & 0 deletions cypress/e2e/linked-list.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { inputTextSelector, inputNumberSelector, DELAY, headSelector, tailSelector, letterSelector, formSelector } from './consts'

const TEXT = 'el'
const checkCircleElement = ({ el, value, state, type }) => {
if (type === 'head') {
el.find('div[class*="head"] div[class*="' + state + '"]')
.should('have.length', 1)
.and('have.text', value)
} else if (type === 'tail') {
el.find('div[class*="tail"] div[class*="' + state + '"]')
.should('have.length', 1)
.and('have.text', value)
} else {
el.find('div[class*="' + state + '"]').should('have.length', 1)
}
}

describe('list page works correctly', () => {
beforeEach(() => {
cy.visit('list')
})

it('add and delete buttons should be disabled when there is nothing to add or delete', () => {
const text = cy.get(inputTextSelector).value
const index = cy.get(inputNumberSelector).value

if (!text) {
cy.contains('Добавить в head').should('have.attr', 'disabled')
cy.contains('Добавить в tail').should('have.attr', 'disabled')
}
if (!text || !index) {
cy.contains('Добавить по индексу').should('have.attr', 'disabled')
cy.contains('Удалить по индексу').should('have.attr', 'disabled')
}
})

it('should display default list correctly', () => {
let length = 0
cy.get(formSelector).next().children('div').as('list')
// eslint-disable-next-line
cy.wait(DELAY)
cy.get('@list').then($list => (length = $list.length))

// eslint-disable-next-line
cy.wait(DELAY)

cy.get('@list').each(($el, index) => {
index === 0 && expect($el.find(headSelector)).have.text('head')
index !== 0 && expect($el.find(headSelector)).have.text('')
index === length - 1 && expect($el.find(tailSelector)).have.text('tail')
index !== length - 1 && expect($el.find(tailSelector)).have.text('')

expect($el.find(letterSelector)).not.have.text('')
expect($el.find('div[class*="default"]')).to.have.length(1)
})
})

it('should add head element correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.get(inputTextSelector).type(TEXT)
cy.contains('Добавить в head').click()

cy.get(formSelector).next().children('div').as('list')
checkCircleElement({ el: cy.get('@list').eq(0), value: TEXT, state: 'changing', type: 'head' })

// eslint-disable-next-line
cy.wait(DELAY)
checkCircleElement({ el: cy.get('@list').eq(0), value: TEXT, state: 'modified' })

// eslint-disable-next-line
cy.wait(DELAY)
checkCircleElement({ el: cy.get('@list').eq(0), value: TEXT, state: 'default' })
})

it('should add tail element correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.get(inputTextSelector).type(TEXT)
cy.contains('Добавить в tail').click()

cy.get(formSelector).next().children('div').as('list')
checkCircleElement({ el: cy.get('@list').last(), value: TEXT, state: 'changing', type: 'head' })

// eslint-disable-next-line
cy.wait(DELAY)
checkCircleElement({ el: cy.get('@list').last(), value: TEXT, state: 'modified' })

// eslint-disable-next-line
cy.wait(DELAY)
checkCircleElement({ el: cy.get('@list').last(), value: TEXT, state: 'default' })
})

it('should delete head element correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
let length = 0
let value = ''
cy.get(formSelector).next().children('div').as('list')
cy.get('@list').then($list => (length = $list.length))
cy.get('@list').first().find(letterSelector)
.then($el => {
value = $el.text()
})
.then(() => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.contains('Удалить из head').click()

checkCircleElement({ el: cy.get('@list').first(), value: value, state: 'changing', type: 'tail' })
cy.get('@list').first().find('div[class*="circle_default"]').should('not.have.text', value)

// eslint-disable-next-line
cy.wait(DELAY)
length <= 1 && cy.get('@list').should('have.length', 0)
length > 1 && cy.get('@list').then($list => {
expect($list.length).to.eq(length - 1)
})
})
.end()
})

it('should delete tail element correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
let length = 0
let value = ''
cy.get(formSelector).next().children('div').as('list')
cy.get('@list').then($list => (length = $list.length))
cy.get('@list').last().find(letterSelector)
.then($el => {
value = $el.text()
})
.then(() => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.contains('Удалить из tail').click()

checkCircleElement({ el: cy.get('@list').last(), value: value, state: 'changing', type: 'tail' })
cy.get('@list').last().find('div[class*="circle_default"]').should('not.have.text', value)

// eslint-disable-next-line
cy.wait(DELAY)
length <= 1 && cy.get('@list').should('have.length', 0)
length > 1 && cy.get('@list').then($list => {
expect($list.length).to.eq(length - 1)
})
})
.end()
})

it('should add element by index correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.get(formSelector).next().children('div').as('list')
cy.get(inputTextSelector).type(TEXT)
cy.get('@list').then(($list) => {
const length = $list.length
const index = Math.floor(Math.random() * length)

cy.get(inputNumberSelector).type(index)
cy.contains('Добавить по индексу').click()

// eslint-disable-next-line
// cy.wait(DELAY)
for (let i = 0; i <= index; i++) {
cy.get('@list').eq(i).find('div[class*="head"] div[class*="changing"]')
.should('have.length', 1)
.and('have.text', TEXT)
i > 0 && cy.get('@list').eq(i - 1).find('div[class*="changing"]').should('have.length', 1)
// eslint-disable-next-line
cy.wait(DELAY)
}

cy.get('@list').eq(index).find('div[class*="modified"]')
.should('have.length', 1)
.and('have.text', TEXT)

// eslint-disable-next-line
cy.wait(DELAY)

cy.get('@list').eq(index).find('div[class*="default"]')
.should('have.length', 1)

cy.get('@list').then(($newList) => {
expect($newList.length).to.eq(length + 1)
})
})
.end()
})

it('should delete element by index correctly', () => {
// eslint-disable-next-line
cy.wait(DELAY)
cy.get(formSelector).next().children('div').as('list')
cy.get('@list').then(($list) => {
const length = $list.length
const index = Math.floor(Math.random() * length)
const value = $list.eq(index).find(letterSelector).eq(0).text()

cy.get(inputNumberSelector).type(index)
cy.contains('Удалить по индексу').click()

// eslint-disable-next-line
cy.wait(DELAY)
for (let i = 0; i < index; i++) {
cy.get('@list').eq(i).find('div[class*="changing"]')
.should('have.length', 1)

// eslint-disable-next-line
cy.wait(DELAY)
}

cy.get('@list').eq(index).find('div[class*="tail"] div[class*="changing"]')
.should('have.length', 1)
.and('have.text', value)
cy.get('@list').eq(index).find(letterSelector).eq(0).should('not.have.text', value)

// eslint-disable-next-line
cy.wait(DELAY)
length <= 1 && cy.get('@list').should('have.length', 0)
length > 1 && cy.get('@list').then(($newList) => {
expect($newList.length).to.eq(length - 1)
})
})
.end()
})
})
Loading