Задать вопрос
  • Как выглядит правильный процесс тестирования?

    M23
    @M23
    Привет.
    1) Заводить баги и тест-кейсы/чек-листы надо отдельно от задач, так как правиться и проверяться они могут сильно позже, когда задачу давно уже закрыли. Например, регресс. Писать в комментах к задаче - плохая практика :)
    2) Кейсы пишутся на документацию к задаче, а не на то, как реализовали. То есть тестовая документация пишется еще до того, как ты приступила к тестированию.
    3) Написанные кейсы можно прилинковать к задачам и наоборот.
    4) Тестовая документация, баги и задачи могут находиться в разных TMS. Например, кейсы/чек-листы в Allure, а задачи и баги в Jira. Или все в Jira, но в отдельном плагине. Тут уж как в компании заведено или какие вы используете TMS.
    5) Баги заводятся как отдельные таски в бэклог. Если это новый функционал, который в работе, то может будет удобнее, если напрямую передашь разработчику и он сразу поправит.

    P.S. Сходи к коллегам из других команд (если такие есть) и посоветуйся с ними. В дальнейшем разговоре с лидом можно будет ссылаться на их мнение. Но менять процесс определенно стоит.
    Ответ написан
    Комментировать
  • Как сделать сортировку HTML объектов в зависимости от чисел внутри элемента?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как получить массивоподобные или итерируемые данные в отсортированном виде - функция сортировки получает данные и функцию, принимающую элемент данных и возвращающую его вес (может быть числом или строкой); собирается массив пар, состоящих из элементов данных и их весов; полученный массив сортируется, функция сравнения проверяет, как веса элементов соотносятся между собой; из отсортированного массива извлекаются элементы исходных данных:

    const sorted = (data, key) => Array
      .from(data, n => [ key(n), n ])
      .sort(([a], [b]) => a < b ? -1 : +(a > b))
      .map(n => n[1]);

    Как отсортировать содержимое DOM-элемента - да просто добавить ему это содержимое в отсортированном виде:

    const sortChildren = (el, key) =>
      el.append(...sorted(el.children, key));

    Направление сортировки будем указывать с помощью data-атрибута:

    <button data-order="-1">От большего к меньшему</button>
    <button data-order="+1">От меньшего к большему</button>

    Кнопкам назначаем общий обработчик клика, где сортируем содержимое .catalog-items (вес элемента - число внутри, умноженное на направление сортировки), кликнутой кнопке класс добавляем, у остальных убираем:

    const wrapper = document.querySelector('.catalog-items');
    const buttons = document.querySelectorAll('[data-order]');
    
    buttons.forEach(n => n.addEventListener('click', onClick));
    
    function onClick({ target: t }) {
      const order = +t.dataset.order;
      sortChildren(wrapper, el => parseInt(el.innerText) * order);
      buttons.forEach(n => n.classList.toggle('active', n === t));
    }
    Ответ написан
    3 комментария
  • Требования к самописной CRM?

    Jeer
    @Jeer
    уверенный пользователь
    Аж жуть берет от таких заданий ) Покупка готового инструмента обычно дешевле, чем разработка с нуля. Особенно если разработка осуществляется одним человеком. Особенно если опыта мало. Особенно, если на поддержке будет тот же человек, что и на разработке ) безумие :) проект полетит в помойку, но у вас будет строчка в резюме по созданию проекта, можете обкатывать любые технологии за счет глупого работодателя.

    По делу без брюзжания:
    Писать под винду моветон - лицензии дорогие
    Вин формс зачем? - делайте веб апи с фронтом на вью/реакте/ангуляре. Нужна кроссплатформенность, чтобы хоть с телефона можно было зайти и нажать нужную кнопку в системе.
    Апи нужно, потому что будет много интеграций с другими системами, загрузка/выгрузка в 1с, не дай бог будете телефонию подключать
    Внутренняя сеть решается с помощью впн сервера.
    Помимо функциональных требований существуют еще технические, должен быть мониторинг, вы должны всегда знать сколько ресурсов потребляет ваш сервер, сколько данных занимает на дисках, логи и трейсы - гуглится по слову Observability, обычно не закладывается в смету, но к этим вопросам приходят рано или поздно
    Что еще, ну, по функционалу тут проще, открываете презентации в популярных CRMках, смотрите, что они могут, выписываете списком и идете к заказчику, чтобы он указал галочками, что будете делать, что не будете
    потом прикидываете по трудозатратам и озвучиваете сроки из которых можно понять примерную стоимость проекта. Часто одно маленькое предложение, типа того же "выгрузить данные в 1с" грозит несколькими десяткми часов работы, потому что другой отдел, с ними нужно договориться и сделать интеграцию. Или "должен быть отчет такой-то", а там как начнешь разбираться, еще 5 раз посовещаться сначала надо ))
    Ответ написан
    Комментировать
  • Как отследить изменения?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Одним из основных способов является подписка на триггер изменений в Таблице, который реализуется в Google Apps Script.

    Вы можете построить свое решение на основе примера https://qna.habr.com/q/1207030#answer_2234340
    Ответ написан
    Комментировать
  • Вопроса нет, и все?

    ThunderCat
    @ThunderCat
    {PHP, MySql, HTML, JS, CSS} developer
    Uncaught SyntaxError: Unexpected token < in JSON at position 0
    Читаем. Переводим.
    Открываем инструменты разработчика, вкладку нетворк. Отправляем наш гениальный запрос - смотрим в неменее гениальный ответ от сервера, в котором наверняка что-то типа "ой-вей, ваш пхп код полный шлак, в котором ошибок больше чем на помойной кошке блох". Исправляем ошибки, и - о чудо! Все заработало!
    Ответ написан
    Комментировать
  • Как добавить условие в регулярное выражение?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    ^(?!.*__)@[a-z][a-z\d_]{4,34}$
    Ответ написан
    1 комментарий
  • Почему мы имеем право решать уравнения методом замены переменной?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Ну, это просто подстановка. Если, как в моем примере, предположить, что z=x^2, то из-за равенства получается и x^2=z. А дальше можно каждый x^2 переписать как z, ведь они равны.

    Или это можно еще понимать как абстрактное мышление. Вот есть у вас уравнение на x. Вы можете заметить какое-то повторяющееся выражение. Оно имеет какое-то значение. Вот это значение можно обозначить новой буквой. Вот вы же можете буквой x обозначить "сколько у вас яблок". Вы точно также можете обозначить буквой z "сколько у вас яблок в квадрате".

    Это можно делать всегда, но в результате этого могут получиться лишние корни. Как например тут, если есть решения с отрицательными z, то никакой x ему не соответствует. Надо аккуратно проверять все значения z и искать соответсвующие им x.

    Кто это придумал, я хз. Наверно примерно тогда же, когда догадались вообще буквы в уравнения вставлять, там же и придумали вставлять их по мере надобности.
    Ответ написан
    1 комментарий
  • Регулярное выражение php длина строки?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    ^\d{8}(\d{4})?$
    Ответ написан
    Комментировать
  • Как реализовать функцию, которая принимает любое неотрицательное целое число и возвращает его цифрами в порядке убывания?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const sortDigits = num => +[...`${num}`].sort((a, b) => b - a).join('');

    или

    const sortDigits = num => ''.concat.apply('', num.toString().split('').sort().reverse()) - 0;

    или

    const sortDigits = num => Number(Array
      .from('' + num)
      .reduce((acc, n) => (acc[n]++, acc), Array(10).fill(0))
      .reduceRight((acc, n, i) => acc + String(i).repeat(n), '')
    );

    или

    const sortDigits = num => Array
      .prototype
      .reduce
      .call(String(num), (acc, n) => ((acc[9 - n] ??= []).push(n | 0), acc), [])
      .flat()
      .reduce((acc, n) => acc * 10 + n, 0);
    Ответ написан
    1 комментарий
  • Как обрезать слишком длинный текст при выводе?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      maxlen: 10,
      items: [
        'hello, world!!',
        'fuck the world',
        'fuck everything',
        '1234567890',
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit,',
       ],
    }),
    methods: {
      short1: (str, maxlen) => str.length <= maxlen ? str : str.slice(0, maxlen) + '...',
      short2: (str, maxlen) => str.substring(0, maxlen) + (str.charAt(maxlen) && '...'),
      short3: (str, maxlen) => str.replace(RegExp(`(.{${maxlen}}).+`), '$1...'),
      short4: (str, maxlen) => str.replace(RegExp(`(?<=.{${maxlen}}).+`), '...'),
    },

    <input type="range" min="1" max="20" v-model="maxlen">
    <span>{{ maxlen }}</span>
    
    <div v-for="n in items">
      <div v-text="short1(n, maxlen)"></div>
      <div v-html="short2(n, maxlen)"></div>
      <div :text-content.prop="short3(n, maxlen)"></div>
      <div>{{ short4(n, maxlen) }}</div>
    </div>

    https://jsfiddle.net/dxm0gsnf/
    Ответ написан
    Комментировать
  • Как выполнять вычисления с помощью функций (результат вызова предыдущей должен быть аргументом следующей)?

    0xD34F
    @0xD34F Куратор тега JavaScript
    "Числовые" функции проверяют, является ли переданное им значение функцией, если да - вызывают её со своим числом в качестве аргумента, нет - просто возвращают число.

    Функции операций принимают второе число, возвращают функцию, принимающую первое число и производящую над переданными числами операцию.

    const [ zero, one, two, three, four, five, six, seven, eight, nine ] = Array.from(
      { length: 10 },
      (_, i) => f => f instanceof Function ? f(i) : i
      // или
      // (_, i) => f => f?.(i) ?? i
    );
    
    const plus = a => b => b + a;
    const minus = a => b => b - a;
    const times = a => b => b * a;
    const dividedBy = a => b => b / a | 0;
    Ответ написан
    Комментировать
  • Как выполнять вычисления с помощью функций (результат вызова предыдущей должен быть аргументом следующей)?

    phaggi
    @phaggi
    лужу, паяю, ЭВМы починяю
    Решаю задачи на codewars, не могу решить задачу с функциями?

    Да, не можете.
    Ответ написан
    Комментировать
  • Как поставить Linux на смартфон?

    Дистр общего назначения типа дебиана, нативно, и с поддержкой всей периферии - точно нет.

    Железо у телефонов сильно специфичное и требует кучи проприетарных драйверов, которых как правило нет в ядре.
    На телефонах даже нет EFI, по тому загрузить даже что-то минимальное типа busybox очень нелегко (
    https://github.com/aligator/init-linux-beside-android
    )

    В теории можно запускать полноценный Linux внутри android:
    https://medium.com/@quantvc/running-debian-on-andr...

    Я бы оставил эту затею и взял бы лучше какой-нибудь одноплатник
    Ответ написан
    9 комментариев
  • Как удалить все классы, начинающиеся с определённой подстроки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кого надо удалить: const classPrefix = 'modal--';

    Удаляем:

    Array.from(el.classList).forEach(n => el.classList.toggle(n, !!n.indexOf(classPrefix)));

    или

    el.classList.remove(...[...el.classList].filter(n => n.startsWith(classPrefix)));

    или

    for (let i = el.classList.length; i--;) {
      if (el.classList[i].search(classPrefix) === 0) {
        el.classList.remove(el.classList[i]);
      }
    }

    или

    el.classList.value = el.classList.value
      .split(' ')
      .filter(RegExp.prototype.test.bind(RegExp(`^(?!${classPrefix})`)))
      .join(' ');

    или

    el.className = el.className.replace(RegExp(`(^| )${classPrefix}\\S*`, 'g'), '').trim();
    Ответ написан
    9 комментариев
  • Как вывести значения false общим числовым количеством?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const statsMeta = [
      { title: 'отредактированные', count: item => +item.edited },
      { title: 'неотредактированные', count: item => +!item.edited },
      { title: 'всего', count: () => 1 },
    ];
    
    const statsData = allMessages.reduce((acc, n) => (
      statsMeta.forEach((m, i) => acc[i] += m.count(n)),
      acc
    ), Array(statsMeta.length).fill(0));
    
    console.log(statsMeta.map((n, i) => `${n.title}: ${statsData[i]}`).join('\n'));
    Ответ написан
    Комментировать
  • Как изменить имена ключей в массиве объектов исходя из другого массива объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr2.map(function(n) {
      return Object.fromEntries(this.map(m => [ m[1], n[m[0]] ]));
    }, arr1.flatMap(Object.entries));

    или

    const keys = Object.entries(Object.assign({}, ...arr1));
    const result = arr2.map(n => keys.reduce((acc, m) => (acc[m[1]] = n[m[0]], acc), {}));
    Ответ написан
    4 комментария
  • Как экранировать стили?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега CSS
    Куда «экранировать»? Зачем «экранировать»? Вы хотите, чтобы стиль магически применялся только к лежащей рядом с ней кнопке? Так не работает. Используйте классы или идентификаторы, если не хотите инлайново писать. Ну или какой-то сложный селектор. Короче, в стиле должно быть явно указано какую button вы имеете в виду от корня документа.
    Ответ написан
    Комментировать
  • Когда стоит вкладывать input в label, а когда нет?

    KulakovAngel
    @KulakovAngel
    Full Stack Developer (Node.JS)
    В целом, с точки зрения правильности/валидности кода, как заметил Danny Arty, разницы нет. В примитивных случаях верстки визуальной разницы тоже особо не наблюдается.

    Но если нужно сверстать что-то посложнее, сделать более интересное оформление, разница появляется, поскольку нам нужно взаимодействовать с разным порядком и вложенностью различных тегов. Сравните:

    1. В таком варианте у нас имеется два рядом расположенных тега. Чтобы выбрать второй, идущий после первого, можно использовать "соседский" селектор "+" (Label идет сразу после Input). Данный вариант более "независимый", так как мы можем менять местами input и label, и даже разносить их на удаленное расстояние.
    <style>
      input + label {
        color: #ff0000;
      }
    </style>
    
    <input type="checkbox" id="checkbox" />
    <label for="checkbox">чекбокс</label>


    2. И второй вариант. Здесь мы не можем только средствами html/css обратиться "от input к label", так как не существует способа обратиться от ребенка к родителю (это можно, конечно, легко сделать через JS). Существуют селекторы потомков и соседей, но не родителей. Можно обратиться только от label к input, что дает мало преимуществ, так как
    1. input плохо стилизуется
    2. label обычно ничем не примечателен в отличие от input, который информативен (содержит, например, атрибут type).

    <style>
      label > input  {
        outline-color: #ff0000;
        outline-style: double;
      }
    </style>
    
    <label>
      <input type="checkbox" />
      чекбокс
    </label>


    А теперь представим, что нам нужно сверстать нечто подобное на основе (см. картинку):
    5ffea6239c1da641320430.png

    Как это реализовать? Для label соорудим ":before" и ":after", которым дадим форму скругленного прямоугольника и круга (который, к тому же будет перемещаться).

    Здесь второй вариант нам явно не подойдет, так как мы бы хотели в зависимости от состояния checkbox (.checkbox:checked) изменять родственный ему label:before (изменять цвет, перемещать).
    Если хотите взглянуть подробнее на код, пожалуйста:

    Таким образом, принципиальной разницы нет, но первый вариант (с id) более универсален, так как
    1. input и label могут быть разнесены физически (находится в разных местах документа)
    2. label может идти после input, что дает нам возможность обратиться в CSS от второго к первому

    Надеюсь, ответил на Ваш вопрос.
    Ответ написан
    Комментировать
  • Как преобразовать массив в под массив + объект?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    «С методами» это в одну строку:
    arr.map(item => Object.fromEntries([item]))

    Разжёванный учебный костыль «без методов»
    const resultArr = [];
    for (let i = 0; i < arr.length; i++) {
      const item = arr[i];
      const obj = {};
      obj[item[0]] = item[1];
      resultArr.push(obj);
    }

    или покороче
    const resultArr = [];
    for (let [prop, value] of arr) {
      const obj = { [prop]: value };
      resultArr.push(obj);
    }
    Ответ написан
    1 комментарий
  • С чего начать системному администратору в школе?

    @Drno
    1. - беги оттуда... работы дохера, денег нифига
    А по теме -

    надо создать "карту" сети, где будут ПК которым нужен доступ, спланировать прокладку сети.
    далее можно поделить участки на "квадраты", чтобы приводить туда 1 кабель и ставить свитч, а не вести кучу проводов до каждого ПК
    после этих подсчетов возвращайтесь - будем подбирать оборудование
    Ответ написан
    10 комментариев