/
sc_coder
/
MentalCheckList
Обзор
Документация
Войти
/
sc_coder
/
MentalCheckList
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/logic.test.js
276 строк
13 KB
ScCoder
Initial commit: Ментальный Чек-Лист PWA
14 июл 2026, 08:35
14 июл 2026, 08:35
482499e
Код
Авторство
О чём код?
var Logic = require('../logic'); describe('clampThreshold', function () { test('оставляет значение в допустимых границах без изменений', function () { expect(Logic.clampThreshold(30)).toBe(30); }); test('поднимает значение ниже минимума до MIN_THRESHOLD', function () { expect(Logic.clampThreshold(5)).toBe(Logic.MIN_THRESHOLD); }); test('опускает значение выше максимума до MAX_THRESHOLD', function () { expect(Logic.clampThreshold(150)).toBe(Logic.MAX_THRESHOLD); }); test('возвращает значение по умолчанию для нечислового входа', function () { expect(Logic.clampThreshold('abc')).toBe(Logic.DEFAULT_THRESHOLD); }); test('округляет дробные значения', function () { expect(Logic.clampThreshold(45.6)).toBe(46); }); }); describe('calculatePercentage', function () { test('считает процент от общего числа вопросов', function () { expect(Logic.calculatePercentage(3, 10)).toBe(30); }); test('возвращает 0, если общее число вопросов равно 0', function () { expect(Logic.calculatePercentage(0, 0)).toBe(0); }); test('округляет до одного знака после запятой', function () { expect(Logic.calculatePercentage(1, 3)).toBe(33.3); }); test('обрабатывает 100%', function () { expect(Logic.calculatePercentage(5, 5)).toBe(100); }); }); describe('getZone', function () { test('возвращает yellow, если процент строго больше порога', function () { expect(Logic.getZone(31, 30)).toBe('yellow'); }); test('возвращает green, если процент равен порогу', function () { expect(Logic.getZone(30, 30)).toBe('green'); }); test('возвращает green, если процент меньше порога', function () { expect(Logic.getZone(10, 30)).toBe('green'); }); }); describe('addQuestion', function () { test('добавляет новый вопрос с флагом custom и без позитивной формулировки, если она не передана', function () { var list = []; var result = Logic.addQuestion(list, ' Новый вопрос '); expect(result).toHaveLength(1); expect(result[0].negativeText).toBe('Новый вопрос'); expect(result[0].positiveText).toBeNull(); expect(result[0].custom).toBe(true); expect(result[0].id).toBeTruthy(); }); test('сохраняет позитивную формулировку, если она передана', function () { var result = Logic.addQuestion([], ' Негатив ', ' Позитив? '); expect(result[0].negativeText).toBe('Негатив'); expect(result[0].positiveText).toBe('Позитив?'); }); test('пустая позитивная формулировка (пробелы) сохраняется как null', function () { var result = Logic.addQuestion([], 'Негатив', ' '); expect(result[0].positiveText).toBeNull(); }); test('не мутирует исходный список', function () { var list = [{ id: 'a', negativeText: 'A' }]; Logic.addQuestion(list, 'B'); expect(list).toHaveLength(1); }); test('выбрасывает ошибку для пустой негативной формулировки', function () { expect(function () { Logic.addQuestion([], ' '); }).toThrow(); }); test('генерирует уникальные id для разных вызовов', function () { var list = Logic.addQuestion([], 'A'); list = Logic.addQuestion(list, 'B'); expect(list[0].id).not.toBe(list[1].id); }); }); describe('removeQuestion', function () { test('удаляет вопрос по id', function () { var list = [{ id: 'a' }, { id: 'b' }]; expect(Logic.removeQuestion(list, 'a')).toEqual([{ id: 'b' }]); }); test('не изменяет список, если id не найден', function () { var list = [{ id: 'a' }]; expect(Logic.removeQuestion(list, 'zzz')).toEqual(list); }); }); describe('isQuestionActive', function () { test('true, если вопрос присутствует в списке', function () { expect(Logic.isQuestionActive([{ id: 'a' }], 'a')).toBe(true); }); test('false, если вопроса нет в списке', function () { expect(Logic.isQuestionActive([{ id: 'a' }], 'b')).toBe(false); }); }); describe('toggleDefaultQuestion', function () { var poolQ = { id: 'd1', negativeText: 'Негатив', positiveText: 'Позитив?' }; test('добавляет вопрос пула, если shouldBeActive=true и его ещё нет', function () { var result = Logic.toggleDefaultQuestion([], poolQ, true); expect(result).toHaveLength(1); expect(result[0].id).toBe('d1'); expect(result[0].negativeText).toBe('Негатив'); expect(result[0].positiveText).toBe('Позитив?'); expect(result[0].custom).toBe(false); }); test('удаляет вопрос пула, если shouldBeActive=false и он активен', function () { var list = [{ id: 'd1', negativeText: 'Негатив', positiveText: 'Позитив?', custom: false }]; expect(Logic.toggleDefaultQuestion(list, poolQ, false)).toEqual([]); }); test('ничего не меняет, если состояние уже соответствует запрошенному', function () { var list = [{ id: 'd1', negativeText: 'Негатив', positiveText: 'Позитив?', custom: false }]; expect(Logic.toggleDefaultQuestion(list, poolQ, true)).toBe(list); expect(Logic.toggleDefaultQuestion([], poolQ, false)).toEqual([]); }); }); describe('DEFAULT_QUESTIONS', function () { test('содержит 10 вопросов с непустыми негативной и позитивной формулировками', function () { expect(Logic.DEFAULT_QUESTIONS).toHaveLength(10); Logic.DEFAULT_QUESTIONS.forEach(function (q) { expect(q.id).toBeTruthy(); expect(q.negativeText.length).toBeGreaterThan(0); expect(q.positiveText.length).toBeGreaterThan(0); expect(q.negativeText).not.toBe(q.positiveText); }); }); }); describe('pickVariant', function () { var withPositive = { id: 'd1', negativeText: 'Негатив', positiveText: 'Позитив?' }; var withoutPositive = { id: 'c1', negativeText: 'Свой вопрос', positiveText: null }; test('всегда возвращает negative, если нет позитивной формулировки', function () { expect(Logic.pickVariant(withoutPositive, 0.1)).toBe('negative'); expect(Logic.pickVariant(withoutPositive, 0.9)).toBe('negative'); }); test('возвращает positive для randomValue < 0.5', function () { expect(Logic.pickVariant(withPositive, 0.2)).toBe('positive'); }); test('возвращает negative для randomValue >= 0.5', function () { expect(Logic.pickVariant(withPositive, 0.5)).toBe('negative'); expect(Logic.pickVariant(withPositive, 0.8)).toBe('negative'); }); }); describe('getQuestionPromptText', function () { var question = { negativeText: 'Негатив', positiveText: 'Позитив?' }; test('возвращает positiveText для варианта positive', function () { expect(Logic.getQuestionPromptText(question, 'positive')).toBe('Позитив?'); }); test('возвращает negativeText для варианта negative', function () { expect(Logic.getQuestionPromptText(question, 'negative')).toBe('Негатив'); }); }); describe('isSymptomPresent', function () { test('вариант negative: "Да" значит симптом присутствует', function () { expect(Logic.isSymptomPresent('negative', true)).toBe(true); expect(Logic.isSymptomPresent('negative', false)).toBe(false); }); test('вариант positive: "Да" значит всё в норме — симптом не засчитывается', function () { expect(Logic.isSymptomPresent('positive', true)).toBe(false); expect(Logic.isSymptomPresent('positive', false)).toBe(true); }); }); describe('formatDateISO', function () { test('форматирует дату как YYYY-MM-DD с ведущими нулями', function () { var date = new Date(2026, 0, 5); // 5 января 2026 expect(Logic.formatDateISO(date)).toBe('2026-01-05'); }); }); describe('formatDateDisplay', function () { test('форматирует дату в читаемом виде на русском', function () { var date = new Date(2026, 6, 14); // 14 июля 2026 expect(Logic.formatDateDisplay(date)).toBe('14 июля 2026'); }); }); describe('buildHistoryEntry', function () { var questions = [{ id: 'q1' }, { id: 'q2' }, { id: 'q3' }, { id: 'q4' }]; test('считает checkedCount, percentage и зону корректно', function () { var answers = { q1: true, q2: true, q3: false, q4: false }; var entry = Logic.buildHistoryEntry('2026-07-14', questions, answers, 30); expect(entry.checkedCount).toBe(2); expect(entry.totalCount).toBe(4); expect(entry.percentage).toBe(50); expect(entry.zone).toBe('yellow'); expect(entry.date).toBe('2026-07-14'); }); test('зелёная зона, когда процент не превышает порог', function () { var answers = { q1: true, q2: false, q3: false, q4: false }; var entry = Logic.buildHistoryEntry('2026-07-14', questions, answers, 30); expect(entry.zone).toBe('green'); }); test('сохраняет ответы в результирующей записи', function () { var answers = { q1: true }; var entry = Logic.buildHistoryEntry('2026-07-14', questions, answers, 30); expect(entry.answers).toBe(answers); }); }); describe('isValidTimeString', function () { test('принимает корректные значения HH:MM', function () { expect(Logic.isValidTimeString('09:30')).toBe(true); expect(Logic.isValidTimeString('23:59')).toBe(true); expect(Logic.isValidTimeString('00:00')).toBe(true); }); test('отвергает некорректные значения', function () { expect(Logic.isValidTimeString('24:00')).toBe(false); expect(Logic.isValidTimeString('12:60')).toBe(false); expect(Logic.isValidTimeString('9:30')).toBe(false); expect(Logic.isValidTimeString('')).toBe(false); expect(Logic.isValidTimeString(null)).toBe(false); expect(Logic.isValidTimeString(undefined)).toBe(false); }); }); describe('shouldNotifyNow', function () { var today = '2026-07-14'; test('false, если время напоминания некорректно или не задано', function () { expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 21, 0), null, null, today, false)).toBe(false); expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 21, 0), 'bad', null, today, false)).toBe(false); }); test('false, если чек-лист на сегодня уже пройден', function () { expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 21, 0), '20:00', null, today, true)).toBe(false); }); test('false, если уже уведомляли сегодня', function () { expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 21, 0), '20:00', today, today, false)).toBe(false); }); test('false, если текущее время раньше времени напоминания', function () { expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 19, 59), '20:00', null, today, false)).toBe(false); }); test('true, если время напоминания наступило, чек-лист не пройден и уведомления ещё не было', function () { expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 20, 0), '20:00', null, today, false)).toBe(true); expect(Logic.shouldNotifyNow(new Date(2026, 6, 14, 23, 0), '20:00', 'вчера', today, false)).toBe(true); }); }); describe('getMonthMatrix', function () { test('количество ячеек кратно 7', function () { var weeks = Logic.getMonthMatrix(2026, 6); // июль 2026 weeks.forEach(function (week) { expect(week).toHaveLength(7); }); }); test('содержит все дни месяца ровно один раз', function () { var weeks = Logic.getMonthMatrix(2026, 1); // февраль 2026 (не високосный) var days = weeks.flat().filter(Boolean); expect(days).toHaveLength(28); expect(days[0].getDate()).toBe(1); expect(days[days.length - 1].getDate()).toBe(28); }); test('первая неделя начинается с понедельника (null-заполнение до первого дня)', function () { // 1 июля 2026 — среда, значит перед ним должно быть 2 пустые ячейки (Пн, Вт) var weeks = Logic.getMonthMatrix(2026, 6); expect(weeks[0][0]).toBeNull(); expect(weeks[0][1]).toBeNull(); expect(weeks[0][2].getDate()).toBe(1); }); });