Нод и нок чисел правило: § Наименьшее общее кратное. Как найти НОК

Содержание

НОД чисел и НОК чисел

Авторы:
Беджисов Хетаг ученик 10класса
Гагиева Анжелика Олеговна
учитель математики
МКОУ СОШ с.Новый Батако
Правило №1
НОД чисел
НОК чисел
Правило №2

3. 1) Найти НОД (75,95)

Решение
НОД (75,95) 5
75 3 5 5
95 5 19
общий множитель
равен 5
НОД(75,95) 5
5

4. 2)Найдите НОД(84,96)

Решение
НОД (84,96) 12
84 2 2 3 7
96 2 2 2 2 2 3
общие множители
в разложении
2,2,3
НОД(84,96) 2 2 3
12
12

5. 3)Найдите НОД(125,110)

Решение
НОД(125,110) 5
125 5 5 5
110 2 5 11
единственный общий
множитель в разложении
равен 5
НОД (125,110) 5
2
5

6. 4)Найдите НОД(121,98)

НОД (121,98) 1
Решение
121 11 11
98 2 7 7
Общих множителей
в разложении нет
числа взамнопростые и
НОД(121,98 ) 1
1

7. 5)Найдите НОД(82,164)

Решение
НОД (82,164) 82
Так как 164 нацело
делится на 82,
то
НОД(82,164 ) 82
82

8.

6)Найдите НОД(81,63)

Решение
НОД (81,63) 9
81 3 3 3 3
63 3 3 7
общие множители
в разложении 3 и3
НОД(81,63) 3 3 9
9

9. 7) Найдите НОД(184,242)

Решение
НОД (184,242) 2
184 2 2 2 23
242 2 11 11
единственный общий
множитель в разложении
равен 2
НОД(184,24 2) 2
2

10. 8)Найдите НОД(170,265)

Решение
НОД (170,265) 5
170 2 5 17
265 5 53
единственный общий
множитель
в разложении равен 5
НОД(170,26 5) 5
5

11. 9)Найдите НОК(42, 54)

Решение
НОК (42,54) 378
42 2 3 7
54 2 3 3 3
Выпишем большее
из чисел и умножим его
на неподчеркнутый
множитель в разложении
меньшего числа
НОК(42,54) 54 7 378
378

12. 10)Найдите НОК(38, 70)

Решение
НОК (42,54) 1330
38 2 19
70 2 5 7
Выпишем большее
из чисел и умножим его
на неподчеркнутый
множитель в разложении
меньшего числа
НОК(38,70) 70 19 1330
1330

13.

11)Найдите НОК(28, 74)

Решение
НОК (28,74) 1036
28 2 2 7
74 2 37
Выпишем большее
из чисел и умножим его
на неподчеркнутые
множители в разложении
меньшего числа
НОК(28.74) 74 2 7 1036
1036

14. 12)Найдите НОК(32, 55)

НОК (32,55) 1760
Решение
32 2 2 2 2 2
55 5 11
В разложениях чисел
нет общих множителей
значит числа взаимнопростые.
НОК ттакихчисел равен
произведению самих чисел
НОК(32,55) 1760
1760

15. 13)Найдите НОК(24, 74)

Решение
НОК (24,74) 888
24 2 2 2 3
74 2 37
Выпишем большее
из чисел и умножим его
на неподчеркнутые
множители в разложении
меньшего числа
НОК(24,74) 74 2 2 3 888
888

16. 14)Найдите НОК(102, 51)

Решение
НОК (102,51) 102
Так как 102 нацело
делится на 52, тт
это число само
является
НОК этих чисел
НОК(102,51) 102
102

17. 15)Найдите НОК(66, 121)

НОК (66,121) 726
Решение
66 2 3 11
121 11 11
Выпишем большее
из чисел и умножим его
на неподчеркнутые
множители в разложении
меньшего числа
НОК(66,121) 121 2 3 726
726

18.

16)Найдите НОК(53, 54)

Решение
НОК (53,54) 2862
Так как 53 и 54 соседние
числа, то они яявялютс
взаимнопростыми.
Значит
НОК (53,54) 53 54 2862
2862

19. Аннотация

Методическое электронное средство содержит
тему «НОД и НОК чисел». Материал может быть
использован дифференцировано:
с высокомотивированными учениками при проверке
знаний на уроке, а со слабомотивированными
учениками в качестве тренажера для занятий в школе
и дома. Подходит для любого УМК.
Целевая аудитория 5 -6 классы.
Инструкция
На главном слайде (2) показаны две темы
электронного ресурса: «НОД И НОК чисел».
Определившись с номером задания вы можете
выбрать вопрос, кликнув на него мышкой. Решив
данное задание, вы всегда можете его проверить,
кликнув мышкой на , расположенного в нижнем
левом углу. Если вы затрудняетесь с решением
задания, Вы всегда можете получить информацию о
том, как решить данное задание, кликнув мышкой на
Решение
. Для того, чтобы выбрать следующий
вопрос -кликните на
и вы вернетесь на
основную страницу.

21. Чтобы найти НОД чисел:

1)Разложить на простые множители данные
числа;
2) Подчеркнуть в разложении общие
множители ,
3)Выписать подчеркнутые множители из
разложения любого из чисел, затем
умножить их друг на друга.
4)Получившееся в результате умножения
число и есть наибольший общий делитель

22. Чтобы найти НОК чисел:

1)Разложить на простые множители данные
числа;
2) Зачеркнуть в разложении общие множители
3)Выписать большее из данных чисел, а из
разложения меньшего числа выписать
незачеркнутые множители
4)Умножить эти числа на большее из данных
чисел

правила в математике, алгоритм, формула с примерами

Наименьшее общее кратное — что это такое

Определение

Число, которое можно без остатка разделить на выбранные числа, является их общим кратным. Наименьшее из таких чисел — наименьшее общее кратное или сокращенно «нок».

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

Пример

К числам, кратным 8, относятся 16, 24, 32, 40 и т.п. Кратными 9-ти являются 9, 18, 27, 36 и т.п.

Осторожно! Если преподаватель обнаружит плагиат в работе, не избежать крупных проблем (вплоть до отчисления). Если нет возможности написать самому, закажите тут.

Существует бесчисленное множество чисел, делящихся на а без остатка, т.е. кратных ему. В то же время, этого нельзя сказать о числе делителей. Так, делителями для 9-ти являются 9, 3, 1.

Если для двух или более натуральных чисел существует число, делящееся на оба без остатка, то оно является наименьшим общим кратным. А то из, них, которое самое маленькое, является нок.

Вычисление НОК, правила в математике

Для нахождения нок в математике существует несколько правил или алгоритмов. Самый простой вариант — вычисление НОК для двух чисел-участников. Способ легкий, но приемлем для маленьких натуральных чисел.

Нужно составить ряды чисел, кратных каждому из выбранных значений.

Пример

К (4) — 4, 8, 12, 16, 20, 24;

К (6) — 6, 12, 18, 24, 30.

Из рядов видно, что в обоих рядах встречаются числа 12 и 24. Это общие кратные. Однако 12 из них — меньшее число.

Поэтому НОК (4, 6) — 12.

Как найти НОК через НОД

Определение НОК можно провести с использованием НОД (наибольшего общего делителя).

В этом блоке изложения материала следует уточнить некоторые понятия.

Определение

Простым называется такое натуральное число, которое целиком можно разделить только само на себя либо на единицу.

Наименьшим простым числом является двойка. Она же — единственное четное натуральное простое число. Все остальные — нечетные.

Множество чисел делятся не только на 1 и на себя, но и на другие целые натуральные числа:

8 делится на 1, 2, 4, 8;

36 — на 1, 2, 3, 4, 6, 8 и т. д.

Эти числа — делители восьми и тридцати шести (делимых). Именно они могут разделить 8 и 36 без остатка. В обоих приведенных примерах делимые (8, 36) являются составными числами, поскольку имеют более двух делителей.

В приведенных рядах существуют одинаковые делители. Это 1, 2, 4, 8.

Самое большое число — 8. Оно и является наибольшим общим делителем.

Определение

Наибольший общий делитель (НОД) — число, на которое без остатка делится выбранная пара (либо больше) чисел.

Пример

НОД (9, 45)=9

НОД (12, 48)=12

Бывают пары чисел, которые из общих делителей имеют только единицу. Тогда они называются взаимно простыми: НОД (9, 8)=1, НОД (12, 10)=1.

На следующем примере показаны пары чисел со значениями их НОД и НОК.



 

Решение задачи по нахождению НОК через НОД сводится к следующей формуле:

НОК чисел a,b равняется частному произведения a и b на наибольший общий делитель чисел a и b (по-другому НОД (a, b).

Исходя из этого заключения получается, что НОК и НОД взаимосвязаны друг с другом. Наименьшее общее кратное можно легко найти через наибольший общий делитель для двух или более натуральных чисел.

Как найти НОК через разложение чисел

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

Найденные простые множители первого разложения сравниваются с аналогичными из второго разложения, после чего они перемножаются.

Пример

После разложения числа 9 на простые множители получается ряд:

1, 3, 9.

После разложения 12-ти получается ряд:

1, 2, 3, 4, 6, 12.

После разложения на множители числа 9 получаем: 3*3. После разложения на множители 12-ти получаем: 2*2*3. Объединяя множители обеих вариантов, получаем произведение: 3*3*2*2=36.

Наименьшее общее кратное чисел 9 и 12 — 36.

В качестве проверки произведем действия:

  1. 36/12=3
  2. 9/3=3

На практике записывают: НОК (9, 12)=36.

Такими действиями можно найти НОК более сложных чисел.

Пример

Найти НОК чисел 50 и 180.

Число 50 делится на 1, 2, 5, 10, 25, 50.

Число 180 на: 1, 5, 15, 30, 45, 90, 180.

Разложив на множители 50, получаем: 2, 5, 5.

Разложив 180, получаем: 2, 2, 3, 3, 5.

Из первого разложения выписываем: 2*5*5. Сравнивая со вторым разложением, описываем одну двойку и две тройки. После перемножения полученного ряда получается произведение: 2*5*5*2*3*3=900. Это и есть наименьшее общее кратное чисел 50 и 180.

Следовательно, НОК (50, 180)=900.

Существует еще один быстрый способ находить НОК. Он приемлем для вариантов, когда одно число нацело делится на другое. Например: НОК (15, 30)=30, НОК (20, 80)=80, НОК (16, 48)=48.

Для случаев, когда у двух чисел не имеется общих делителей, их можно просто перемножить и получить НОК. Например, НОК (7, 8)=56, НОК (4, 9)=36, НОК (7, 9)=63.

Нахождение НОК трех и большего количества чисел

Если предстоит найти НОК для большего, чем 2, количества чисел, их нужно разложить на простые множители. Например,

32=2*2*2*2*2;

40=2*2*2*5;

80=2*2*2*2*5

Сравнивая множители в каждом случае разложения натуральных чисел и выстраивая их в один ряд для умножения, получаем, что НОК (32, 40, 80) = 2*2*2*2*2*5 = 160.

В математике принято для нахождения НОК трех и более чисел применять следующую теорему:

Если имеется ряд чисел (а1, а2, а3…аk), можно найти НОК mk этих чисел производя последовательные вычисления: m2=НОК (а1, а2), m3=НОК (а2, а3)… mk=НОК (mk-1, аk)

Пример

Дано задание вычислить НОК для чисел 140 (a1), 9 (a2), 54 (а3), 250 (а4).

Тогда m2=НОК (a1, a2)=НОК (140, 9).

Для нахождения НОК (140, 9) производим действия. 140=15*9+5; 9=5*1+4.

Последующее разложение: 5=4*1+1, 4=4*1.

Следовательно, НОД (140, 9)=1. НОК (140, 9)=140*9/НОД (140, 9)=140*9/1=1260.

Ответ: m2=1260

По аналогии вычисляем m3 (=3780) и m4 (=94500). Это и есть ответ решения задачи по нахождению НОК чисел 140, 9, 54, 250.

Тренажёр «НОД и НОК чисел»

Слайды и текст этой онлайн презентации

Слайд 1

Тренажер «НОД и НОК чисел»
Авторы: Беджисов Хетаг ученик 10класса Гагиева Анжелика Олеговна учитель математики МКОУ СОШ с.Новый Батако

Слайд 2

НОК чисел
НОД чисел
Правило №1
Правило №2

Слайд 3

1) Найти НОД (75,95)
Решение

Слайд 4

2)Найдите НОД(84,96)
Решение

Слайд 5

3)Найдите НОД(125,110)
Решение

Слайд 6

4)Найдите НОД(121,98)
Решение

Слайд 7

5)Найдите НОД(82,164)
Решение

Слайд 8

6)Найдите НОД(81,63)
Решение

Слайд 9

7) Найдите НОД(184,242)
Решение

Слайд 10

8)Найдите НОД(170,265)
Решение

Слайд 11

9)Найдите НОК(42, 54)

Слайд 12

10)Найдите НОК(38, 70)

Слайд 13

11)Найдите НОК(28, 74)

Слайд 14

12)Найдите НОК(32, 55)

Слайд 15

13)Найдите НОК(24, 74)

Слайд 16

14)Найдите НОК(102, 51)

Слайд 17

15)Найдите НОК(66, 121)

Слайд 18

16)Найдите НОК(53, 54)

Слайд 19

Аннотация
Методическое электронное средство содержит тему «НОД и НОК чисел». Материал может быть использован дифференцировано: с высокомотивированными учениками при проверке знаний на уроке, а со слабомотивированными учениками в качестве тренажера для занятий в школе и дома. Подходит для любого УМК. Целевая аудитория 5 -6 классы.

Слайд 20

Инструкция

Решение
На главном слайде (2) показаны две темы электронного ресурса: «НОД И НОК чисел». Определившись с номером задания вы можете выбрать вопрос, кликнув на него мышкой. Решив данное задание, вы всегда можете его проверить, кликнув мышкой на , расположенного в нижнем левом углу. Если вы затрудняетесь с решением задания, Вы всегда можете получить информацию о том, как решить данное задание, кликнув мышкой на . Для того, чтобы выбрать следующий вопрос -кликните на и вы вернетесь на основную страницу.

Слайд 21

Чтобы найти НОД чисел:
1)Разложить на простые множители данные числа; 2) Подчеркнуть в разложении общие множители , 3)Выписать подчеркнутые множители из разложения любого из чисел, затем умножить их друг на друга. 4)Получившееся в результате умножения число и есть наибольший общий делитель

Слайд 22

Чтобы найти НОК чисел:
1)Разложить на простые множители данные числа; 2) Зачеркнуть в разложении общие множители 3)Выписать большее из данных чисел, а из разложения меньшего числа выписать незачеркнутые множители 4)Умножить эти числа на большее из данных чисел

Как найти нок и нод трех чисел. Нахождение нок и нод правило. Нахождение НОД с помощью алгоритма Евклида

Наибольший общий делитель

Определение 2

Если натуральное число a делится на натуральное число $b$, то $b$ называют делителем числа $a$, а число $a$ называют кратным числа $b$.

Пусть $a$ и $b$-натуральные числа. Число $c$ называют общим делителем и для $a$ и для $b$.

Множество общих делителей чисел $a$ и $b$ конечно, так как ни один из этих делителей не может быть больше, чем $a$. Значит,среди этих делителей есть наибольший, который называют наибольшим общим делителем чисел $a$ и $b$ и для его обозначения используют записи:

$НОД \ (a;b) \ или \ D \ (a;b)$

Чтобы найти наибольший общий делитель двух, чисел необходимо:

  1. Найти произведение чисел, найденных на шаге 2. Полученное число и будет искомым наибольшим общим делителем.

Пример 1

Найти НОД чисел $121$ и $132.$

    $242=2\cdot 11\cdot 11$

    $132=2\cdot 2\cdot 3\cdot 11$

    Выбрать числа, которые входят в разложение этих чисел

    $242=2\cdot 11\cdot 11$

    $132=2\cdot 2\cdot 3\cdot 11$

    Найти произведение чисел, найденных на шаге 2.Полученное число и будет искомым наибольшим общим делителем.

    $НОД=2\cdot 11=22$

Пример 2

Найти НОД одночленов $63$ и $81$.

Будем находить согласно представленному алгоритму. Для этого:

    Разложим числа на простые множители

    $63=3\cdot 3\cdot 7$

    $81=3\cdot 3\cdot 3\cdot 3$

    Выбираем числа, которые входят в разложение этих чисел

    $63=3\cdot 3\cdot 7$

    $81=3\cdot 3\cdot 3\cdot 3$

    Найдем произведение чисел, найденных на шаге 2.Полученное число и будет искомым наибольшим общим делителем.

    $НОД=3\cdot 3=9$

Найти НОД двух чисел можно и по-другому, используя множество делителей чисел.

Пример 3

Найти НОД чисел $48$ и $60$.

Решение:

Найдем множество делителей числа $48$: $\left\{{\rm 1,2,3.4.6,8,12,16,24,48}\right\}$

Теперь найдем множество делителей числа $60$:$\ \left\{{\rm 1,2,3,4,5,6,10,12,15,20,30,60}\right\}$

Найдем пересечение этих множеств: $\left\{{\rm 1,2,3,4,6,12}\right\}$- данное множество будет определять множество общих делителей чисел $48$ и $60$. Наибольший элемент в данном множестве будет число $12$. Значит наибольший общий делитель чисел $48$ и $60$ будет $12$.

Определение НОК

Определение 3

Общим кратным натуральных чисел
$a$ и $b$ называется натуральное число, которое кратно и $a$ и $b$.

Общими кратными чисел называются числа которые делятся на исходные без остатка.Например для чисел $25$ и $50$ общими кратными будут числа $50,100,150,200$ и т.д

Наименьшее из общих кратных будет называться наименьшим общим кратным и обозначается НОК$(a;b)$ или K$(a;b).$

Чтобы найти НОК двух чисел, необходимо:

  1. Разложить числа на простые множители
  2. Выписать множители, входящие в состав первого числа и добавить к ним множители, которые входят в состав второго и не ходят в состав первого

Пример 4

Найти НОК чисел $99$ и $77$.

Будем находить согласно представленному алгоритму. Для этого

    Разложить числа на простые множители

    $99=3\cdot 3\cdot 11$

    Выписать множители, входящие в состав первого

    добавить к ним множители, которые входят в состав второго и не ходят в состав первого

    Найти произведение чисел, найденных на шаге 2.Полученное число и будет искомым наименьшим общим кратным

    $НОК=3\cdot 3\cdot 11\cdot 7=693$

    Составление списков делителей чисел часто очень трудоемкое занятие. Существует способ нахождение НОД, называемый алгоритмом Евклида.

    Утверждения, на которых основан алгоритм Евклида:

    Если $a$ и $b$ —натуральные числа, причем $a\vdots b$, то $D(a;b)=b$

    Если $a$ и $b$ —натуральные числа, такие что $b

Пользуясь $D(a;b)= D(a-b;b)$, можно последовательно уменьшать рассматриваемые числа до тех пор, пока не дойдем до такой пары чисел, что одно из них делится на другое. Тогда меньшее из этих чисел и будет искомым наибольшим общим делителем для чисел $a$ и $b$.

Свойства НОД и НОК

  1. Любое общее кратное чисел $a$ и $b$ делится на K$(a;b)$
  2. Если $a\vdots b$ , то К$(a;b)=a$
  3. Если К$(a;b)=k$ и $m$-натуральное число, то К$(am;bm)=km$

    Если $d$-общий делитель для $a$ и $b$,то К($\frac{a}{d};\frac{b}{d}$)=$\ \frac{k}{d}$

    Если $a\vdots c$ и $b\vdots c$ ,то $\frac{ab}{c}$ — общее кратное чисел $a$ и $b$

    Для любых натуральных чисел $a$ и $b$ выполняется равенство

    $D(a;b)\cdot К(a;b)=ab$

    Любой общийй делитель чисел $a$ и $b$ является делителем числа $D(a;b)$

Определение.
Наибольшее натуральное число, на которое делятся без остатка числа а и b, называют
наибольшим общим делителем (НОД)
этих чисел.

Найдём наибольший общий делитель чисел 24 и 35.
Делителями 24 будут числа 1, 2, 3, 4, 6, 8, 12, 24, а делителями 35 будут числа 1, 5, 7, 35.
Видим, что числа 24 и 35 имеют только один общий делитель — число 1. Такие числа называют взаимно простыми
.

Определение.
Натуральные числа называют взаимно простыми
, если их наибольший общий делитель (НОД) равен 1.

Наибольший общий делитель (НОД)
можно найти, не выписывая всех делителей данных чисел.

Разложим на множители числа 48 и 36, получим:
48 = 2 * 2 * 2 * 2 * 3, 36 = 2 * 2 * 3 * 3.
Из множителей, входящих в разложение первого из этих чисел, вычеркнем те, которые не входят в разложение второго числа
(т. е. две двойки).
Остаются множители 2 * 2 * 3. Их произведение равно 12. Это число и является наибольшим общим делителем чисел 48 и 36.
Так же находят наибольший общий делитель трёх и более чисел.

Чтобы найти наибольший общий делитель

2) из множителей, входящих в разложение одного из этих чисел, вычеркнуть те, которые не входят в разложение других чисел;
3) найти произ ведение оставшихся множителей.

Если все данные числа делятся на одно из них, то это число и является наибольшим общим делителем
данных чисел.
Например, наибольшим общим делителем чисел 15, 45, 75 и 180 будет число 15, так как на него делятся все остальные числа: 45, 75 и 180.

Наименьшее общее кратное (НОК)

Определение.
Наименьшим общим кратным (НОК)
натуральных чисел а и b называют наименьшее натуральное число,
которое кратно и a и b.
Наименьшее общее кратное (НОК) чисел 75 и 60 можно найти и не выписывая подряд кратные этих чисел. Для этого разложим 75 и 60 на
простые множители: 75 = 3 * 5 * 5, а 60 = 2 * 2 * 3 * 5.
Выпишем множители, входящие в разложение первого из этих чисел, и добавим к ним недостающие множители 2 и 2 из разложения
второго числа (т.е. объединяем множители).
Получаем пять множителей 2 * 2 * 3 * 5 * 5, произведение которых равно 300. Это число является наименьшим общим кратным чисел 75 и 60.

Так же находят наименьшее общее кратное для трёх и более чисел.

Чтобы найти наименьшее общее кратное
нескольких натуральных чисел, надо:
1) разложить их на простые множители;
2) выписать множители, входящие в разложение одного из чисел;
3) добавить к ним недостающие множители из разложений остальных чисел;
4) найти произведение получившихся множителей.

Заметим, что если одно из данных чисел делится на все остальные числа, то это число и является наименьшим общим кратным данных
чисел.
Например, наименьшим общим кратным чисел 12, 15, 20 и 60 будет число 60, так как оно делится на все данные числа.

Пифагор (VI в. до н. э.) и его ученики изучали вопрос о делимости чисел. Число, равное сумме всех его делителей (без самого числа),
они называли совершенным числом. Например, числа 6 (6 = 1 + 2 + 3), 28 (28 = 1 + 2 + 4 + 7 + 14) совершенные. Следующие совершенные
числа — 496, 8128, 33 550 336. Пифагорейцы знали только первые три совершенных числа. Четвёртое — 8128 — стало известно в I в. н. э.
Пятое — 33 550 336 — было найдено в XV в. К 1983 г. было известно уже 27 совершенных чисел. Но до сих пор учёные не знают, есть ли
нечётные совершенные числа, есть ли самое большое совершенное число.
Интерес древних математиков к простым числам связан с тем, что любое число либо простое, либо может быть представлено в виде
произведения простых чисел, т. е. простые числа — это как бы кирпичики, из которых строятся остальные натуральные числа.
Вы, наверное, обратили внимание, что простые числа в ряду натуральных чисел встречаются неравномерно — в одних частях ряда их больше,
в других — меньше. Но чем дальше мы продвигаемся по числовому ряду, тем реже встречаются простые числа. Возникает вопрос: существует
ли последнее (самое большое) простое число? Древнегреческий математик Евклид (III в. до н. э.) в своей книге «начала», бывшей на
протяжении двух тысяч лет основным учебником математики, доказал, что простых чисел бесконечно много, т. е. за каждым простым числом
есть ещё большее простое число.
Для отыскания простых чисел другой греческий математик того же времени Эратосфен придумал такой способ. Он записывал все числа
от 1 до какого-то числа, а потом вычёркивал единицу, которая не является ни простым, ни составным числом, затем вычёркивал через
одно все числа, идущие после 2 (числа, кратные 2, т. е. 4, 6, 8 и т. д.). Первым оставшимся числом после 2 было 3. Далее
вычёркивались через два все числа, идущие после 3 (числа, кратные 3, т. е. 6, 9, 12 и т. д.). в конце концов оставались
невычеркнутыми только простые числа.

Для нахождения НОД (наибольшего общего делителя) двух чисел необходимо:

2. Найти (подчеркнуть) все общие простые множители в полученных разложениях.

3. Найти произведение общих простых множителей.

Для нахождения НОК (наименьшего общего кратного) двух чисел необходимо:

1. Разложить данные числа на простые множители.

2. Разложение одного из них дополнить теми множителями разложения другого числа, которых нет в разложении первого.

3. Вычислить произведение полученных множителей.

Нахождение НОД

НОД — это наибольший общий делитель.

Чтобы найти наибольший общий делитель нескольких чисел необходимо:

  • определить множители, общие для обоих чисел;
  • найти произведение общих множителей.

Пример нахождения НОД:

Найдем НОД чисел 315 и 245.

315 = 5 * 3 * 3 * 7;

245 = 5 * 7 * 7.

2. Выпишем множители, общие для обоих чисел:

3. Найдем произведение общих множителей:

НОД(315; 245) = 5 * 7 = 35.

Ответ: НОД(315; 245) = 35.

Нахождение НОК

НОК — это наименьшее общее кратное.

Чтобы найти наименьшее общее кратное нескольких чисел необходимо:

  • разложить числа на простые множители;
  • выписать множители, входящие в разложение одного из чисел;
  • допишем к ним недостающие множители из разложения второго числа;
  • найти произведение получившихся множителей.

Пример нахождения НОК:

Найдем НОК чисел 236 и 328:

1. Разложим числа на простые множители:

236 = 2 * 2 * 59;

328 = 2 * 2 * 2 * 41.

2. Выпишем множители, входящие в разложение одного из чисел и допишем к ним недостающие множители из разложения второго числа:

2; 2; 59; 2; 41.

3. Найдем произведение получившихся множителей:

НОК(236; 328) = 2 * 2 * 59 * 2 * 41 = 19352.

Ответ: НОК(236; 328) = 19352.

Делитель — это целое число, на которое другое целое число делится без остатка. Для нескольких чисел можно найти общие делители, среди которых будет наибольший. Именно наибольший общий делитель обладает рядом полезных свойств.

Наибольший общий делитель

Делитель целого числа A – это целое число B, на которое A делится без остатка. К примеру, делители числа 24 — 1, 2, 3, 4, 6, 8, 12, 24. Каждое число делится на себя и на единицу, поэтому эти делители мы можем не учитывать. Числа, которые делятся только на себя и единицу, считаются простыми и обладают рядом уникальных свойств. Однако к большинству чисел мы можем подобрать делители, некоторые из которых будут общими. К примеру, для числа 36 такими делителями будут 2, 3, 4, 6, 9, 12, 18. Большинство из них совпадает с делителями числа 24, приведенными выше, но наибольшим из них является 12. Это и есть НОД пары 24 и 36. Понятие наименьшего общего делителя не имеет смысла, так как это всегда единица.

Нахождение НОД

Для вычисления НОД используется три способа. Первый, самый простой для понимания, но при этом наиболее трудоемкий — это простой перебор всех делителей пары и выбор из них наибольшего. Например, для 12 и 16 НОД находится следующим образом:

  • выписываем делители для 12 — 2, 3, 4 и 6;
  • выписываем делители для 16 — 2, 4 и 8;
  • определяем общие делители чисел — 2, 4;
  • выбираем наибольший из них — 4.

Второй способ сложнее для понимания, но более эффективен в плане вычислений. В этом случае НОД находится путем разложения чисел на простые множители. Для разложения на простые множители необходимо последовательно делить число без остатка на числа из ряда простых 2, 3, 5, 7, 11, 13…

Для тех же чисел НОД вычисляется по такой схеме:

  • раскладываем 12 на простые множители и получаем 2 × 2 × 3;
  • раскладываем 16 — 2 × 2 × 2× 2;
  • отсеиваем несовпадающие множители и получаем 2 × 2;
  • перемножаем множители и определяем НОД = 4.

Третий способ лучше всего подходит для определения НОД пар любых, сколь угодно больших чисел. Алгоритм Евклида — это метод поиска наибольшего общего делителя для пары целых чисел A и B, при условии A>B.

Согласно алгоритму мы должны разделить A на B, в результате которого получится:

где A1 – целое число, C – остаток от деления.

После этого разделим B на остаток C и обозначим результат как B1. Теперь у нас есть новая пара чисел A1 и B1.

Повторим действия. Разделим A1 на B1, получим в результате A2 и C1. После этого разделим B1 на C1 и получим B2. Алгоритм повторяется до тех пор, пока остаток Cn не будет равен нулю.

Рассмотрим его подробно на числах 1729 и 1001. Порядок действий следующий. У нас есть пара (1001, 1729). Для использования алгоритма Евклида первое число в паре должно быть больше. Выполним преобразование для корректной работы алгоритма — меньшее число оставим на месте, а большее заменим на их разницу, так как если оба числа делятся на НОД, то их разность также делится. Получим (1001, 728). Выполним расчеты:

  • (1001, 728) = (728, 273) = (273, 182) — вместо того, чтобы много раз искать разность, можно написать остаток от деления 728 на 273.
  • (273, 182) = (91, 182) = (91, 0) = 91.

Таким образом, НОД пары 1001 и 1729 равен 91.

Использование НОД

На практике наибольший общий делитель применяется при решении диофантовых уравнений вида ax + by = d. Если НОД (a, b) не делит d без остатка, то уравнение не разрешимо в целых числах. Таким образом, диофантово уравнение имеет целые корни только в случае, если отношение d / НОД (a, b) есть целое число.

Наш онлайн-калькулятор позволяет быстро отыскать наибольший общий делитель как для пары, так и для любого произвольного количества чисел.

Примеры из реальной жизни

Школьная задача

В задаче по арифметике требуется найти НОД четырех чисел: 21, 49, 56, 343. Для решения при помощи калькулятора нам потребуется только указать количество чисел и ввести их в соответствующие ячейки. После этого мы получим ответ, что НОД (21, 49, 56, 343) = 7.

Диофантово уравнение

Пусть у нас есть диофантово уравнение вида 1001 х + 1729 у = 104650. Нам необходимо проверить его на разрешимость в целых чисел. Мы уже считали НОД для этой пары при помощи алгоритма Евклида. Давайте проверим правильность выкладок и пересчитаем НОД на калькуляторе. Действительно, НОД (1001, 1729) = 91. Проверяем возможность целочисленного решения по условию d / НОД (a, b) = 104650/91 = 1150. Следовательно, данное уравнение имеет целые корни.

Заключение

Наибольший общий делитель мы проходим еще в школе, но не всегда понимаем, для чего он нужен в будущем. Однако НОД — важный термин в теории чисел и применяется во многих областях математики. Используйте наш калькулятор для поиска НОД любого количества чисел.

Но многие натуральные числа делятся нацело ещё и на другие натуральные числа.

Например
:

Число 12 делится на 1, на 2, на 3, на 4, на 6, на 12;

Число 36 делится на 1, на 2, на 3, на 4, на 6, на 12, на 18, на 36.

Числа, на которые число делится нацело (для 12 это 1, 2, 3, 4, 6 и 12) называются делителями числа
. Делитель натурального числа a
— это такое натуральное число, которое делит данное число a
без остатка. Натуральное число, которое имеет более двух делителей, называется составным
.

Обратите внимание, что числа 12 и 36 имеют общие делители. Это числа: 1, 2, 3, 4, 6, 12. Наибольший из делителей этих чисел — 12. Общий делитель двух данных чисел a
и b
— это число, на которое делятся без остатка оба данных числа a
и b
.

Общим кратным
нескольких чисел называется число, которое делится на каждое из этих чисел. Например
, числа 9, 18 и 45 имеют общее кратное 180. Но 90 и 360 — тоже их общие кратные. Среди всех jбщих кратных всегда есть наименьшее, в данном случае это 90. Это число называется наименьшим
общим кратным (НОК)
.

НОК всегда натуральное число, которое должно быть больше самого большого из чисел, для которых оно определяется.

Наименьшее общее кратное (НОК). Свойства.

Коммутативность:

Ассоциативность:

В частности, если и — взаимно-простые числа , то:

Наименьшее общее кратное двух целых чисел m
и n
является делителем всех других общих кратных m
и n
. Более того, множество общих кратных m, n
совпадает с множеством кратных для НОК(m, n
).

Асимптотики для могут быть выражены через некоторые теоретико-числовые функции.

Так, функция Чебышёва
. А также:

Это следует из определения и свойств функции Ландау g(n)
.

Что следует из закона распределения простых чисел.

Нахождение наименьшего общего кратного (НОК).

НОК(a, b
) можно вычислить несколькими способами:

1. Если известен наибольший общий делитель , можно использовать его связь с НОК:

2. Пусть известно каноническое разложение обоих чисел на простые множители:

где p 1 ,.. .,p k
— различные простые числа, а d 1 ,…,d k
и e 1 ,…,e k
— неотрицательные целые числа (они могут быть нулями, если соответствующее простое отсутствует в разложении).

Тогда НОК (a
,b
) вычисляется по формуле:

Другими словами, разложение НОК содержит все простые множители , входящие хотя бы в одно из разложений чисел a, b
, причём из двух показателей степени этого множителя берётся наибольший.

Пример
:

Вычисление наименьшего общего кратного нескольких чисел может быть сведено к нескольким последовательным вычислениям НОК от двух чисел:

Правило.
Чтобы найти НОК ряда чисел, нужно:

— разложить числа на простые множители;

— перенести во множители искомого произведения самое большое разложение (произведение множителей самого большого числа из заданных), а потом добавить множители из разложения других чисел, которые не встречаются в первом числе или стоят в нем меньшее число раз;

— полученное произведение простых множителей будет НОК заданных чисел.

Любые два и более натуральных чисел имеют свое НОК. Если числа не кратны друг другу или не имеют одинаковых множителей в разложении, то их НОК равно произведению этих чисел.

Простые множители числа 28 (2, 2, 7) дополнили множителем 3 (числа 21), полученное произведение (84) будет наименьшим числом, которое делится на 21 и 28 .

Простые множители наибольшего числа 30 дополнили множителем 5 числа 25, полученное произведение 150 больше самого большого числа 30 и делится на все заданные числа без остатка. Это наименьшее произведение из возможных (150, 250, 300…), которому кратны все заданные числа.

Числа 2,3,11,37 — простые, поэтому их НОК равно произведению заданных чисел.

Правило
. Чтобы вычислить НОК простых чисел, нужно все эти числа перемножить между собой.

Еще один вариант:

Чтобы найти наименьшее общее кратное (НОК) нескольких чисел нужно:

1) представить каждое число как произведение его простых множителей, например:

504 = 2 · 2 · 2 · 3 · 3 · 7 ,

2) записать степени всех простых множителей:

504 = 2 · 2 · 2 · 3 · 3 · 7 = 2 3 · 3 2 · 7 1 ,

3) выписать все простые делители (множители) каждого из этих чисел;

4) выбрать наибольшую степень каждого из них, встретившуюся во всех разложениях этих чисел;

5) перемножить эти степени.

Пример
. Найти НОК чисел: 168, 180 и 3024.

Решение
. 168 = 2 · 2 · 2 · 3 · 7 = 2 3 · 3 1 · 7 1 ,

180 = 2 · 2 · 3 · 3 · 5 = 2 2 · 3 2 · 5 1 ,

3024 = 2 · 2 · 2 · 2 · 3 · 3 · 3 · 7 = 2 4 · 3 3 · 7 1 .

Выписываем наибольшие степени всех простых делителей и перемножаем их:

НОК = 2 4 · 3 3 · 5 1 · 7 1 = 15120.

краткий конспект по теме НОД и НОК

Ответ:

Что такое НОД и НОК?

Наибольший общий делитель нескольких чисел – это наибольшее натуральное целое число, на которое все исходные числа делятся без остатка. Наибольший общий делитель сокращённо записывается как НОД.

Наименьшее общее кратное нескольких чисел – это наименьшее число, которое делится на каждое из исходных чисел без остатка. Наименьшее общее кратное сокращённо записывается как НОК.

Как проверить, что число делится на другое число без остатка?

Чтобы узнать, делится ли одно число на другое без остатка, можно воспользоваться некоторыми свойствами делимости чисел. Тогда, комбинируя их, можно проверять делимость на некоторые их них и их комбинации.

Некоторые признаки делимости чисел

1. Признак делимости числа на 2

Чтобы определить, делится ли число на два (является ли оно чётным), достаточно посмотреть на последнююю цифру этого числа: если она равна 0, 2, 4, 6 или 8, то число чётно, а значит делится на 2.

Пример: определить, делится ли на 2 число 34938.

Решение: смотрим на последнюю цифру: 8 — значит число делится на два.

2. Признак делимости числа на 3

Число делится на 3 тогда, когда сумма его цифр делится на три. Таким образом, чтобы определить, делится ли число на 3, нужно посчитать сумму цифр и проверить, делится ли она на 3. Даже если сумма цифр получилась очень большой, можно повторить этот же процесс вновь.

Пример: определить, делится ли число 34938 на 3.

Решение: считаем сумму цифр: 3+4+9+3+8 = 27. 27 делится на 3, а значит и число делится на три.

3. Признак делимости числа на 5

Число делится на 5 тогда, когда его последняя цифра равна нулю или пяти.

Пример: определить, делится ли число 34938 на 5.

Решение: смотрим на последнюю цифру: 8 — значит число НЕ делится на пять.

4. Признак делимости числа на 9

Этот признак очень похож на признак делимости на тройку: число делится на 9 тогда, когда сумма его цифр делится на 9.

Пример: определить, делится ли число 34938 на 9.

Решение: считаем сумму цифр: 3+4+9+3+8 = 27. 27 делится на 9, а значит и число делится на девять.

Как найти НОД и НОК двух чисел

Как найти НОД двух чисел

Наиболее простым способом вычисления наибольшего общего делителя двух чисел является поиск всех возможных делителей этих чисел и выбор наибольшего из них.

Рассмотрим этот способ на примере нахождения НОД(28, 36):

Раскладываем оба числа на множители: 28 = 1·2·2·7, 36 = 1·2·2·3·3

Находим общие множители, то есть те, которые есть у обоих чисел: 1, 2 и 2.

Вычисляем произведение этих множителей: 1·2·2 = 4 — это и есть наибольший общий делитель чисел 28 и 36.

Как найти НОК двух чисел

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

Для вычисления НОК нужно вычислить произведение исходных чисел и затем разделить его на предварительно найденный НОД. Найдём НОК для тех же чисел 28 и 36:

Находим произведение чисел 28 и 36: 28·36 = 1008

НОД(28, 36), как уже известно, равен 4

НОК(28, 36) = 1008 / 4 = 252.

Нахождение НОД и НОК для нескольких чисел

Наибольший общий делитель можно находить и для нескольких чисел, а не только для двух. Для этого числа, подлежащие поиску наибольшего общего делителя, раскладывают на простые множители, затем находят произведение общих простых множителей этих чисел. Также для нахождение НОД нескольких чисел можно воспользоваться следующим соотношением: НОД(a, b, c) = НОД(НОД(a, b), c).

Аналогичное соотношение действует и для наименьшего общего кратного чисел: НОК(a, b, c) = НОК(НОК(a, b), c)

Пример: найти НОД и НОК для чисел 12, 32 и 36.

Cперва разложим числа на множители: 12 = 1·2·2·3, 32 = 1·2·2·2·2·2, 36 = 1·2·2·3·3.

Найдём обшие множители: 1, 2 и 2.

Их произведение даст НОД: 1·2·2 = 4

Найдём теперь НОК: для этого найдём сначала НОК(12, 32): 12·32 / 4 = 96.

Чтобы найти НОК всех трёх чисел, нужно найти НОД(96, 36): 96 = 1·2·2·2·2·2·3, 36 = 1·2·2·3·3, НОД = 1·2·2·3 = 12.

НОК(12, 32, 36) = 96·36 / 12 = 288.

Наибольший общий делитель, наименьшее общее кратное

Делитель данного числа есть такое число, на которое данное число делится без остатка (нацело). Например, число 9 есть делитель числа 63, число 42 есть делитель числа 126.
Пусть даны два числа 60 и 72.
1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 — делители числа 60.
1, 2, 3, 4, 6, 8, 9, 12, 18, 24, 36, 72 — делители числа 72.
Среди выписанных делителей есть одинаковые 1, 2, 3, 4, 6, 12. Все эти числа называются общими делителями чисел 60 и 72, а наибольшее среди них — наибольшим общим делителем (для чисел 60 и 72 — это число 12). Наибольшим общим делителем нескольких чисел называется наибольшее число, на которое все данные числа делятся без остатка. Наибольший общий делитель n чисел
обозначается НОД, Д или

.

Для нахождения наибольшего общего делителя находят произведение общих простых множителей, причем каждый из них берется с наименьшим из имеющихся показателем.
Взаимно простыми числами называются числа, не имеющие общих делителей, кроме единицы. Иначе говоря, если а и b — взаимно простые числа, то НОД (a; b) = 1.
Наименьшим общим кратным нескольких чисел называется наименьшее число, которое делится на каждое из данных чисел без остатка. Например, для чисел 4 и 6 число 12 есть наименьшее общее кратное; для чисел 12 и 18 наименьшее общее кратное есть число 36. Наименьшее общее кратное n чисел
обозначается НОК,  К или

Для нахождения наименьшего общего кратного находят произведение всех простых множителей, причем каждый из них берется с наибольшим из имеющихся показателем.
Пример 1. Найти НОД и НОК чисел 126, 540, 630.
Решение.

Отсюда:

Ответ: { 18; 3780 }.
Пример 2. Найти НОД и НОК чисел 144, 1008, 1224.
Решение.

Отсюда:

Ответ: {72; 17136}.
Для любых натуральных чисел а и b справедливо равенство НОД(а;b)• НОК(а;b) =а•b.
В частности, если числа а и b взаимно простые, т. е. НОД(а;b)=1, то НОК(а;b) = ab. Это означает, что наименьшее общее кратное двух взаимно простых чисел равно произведению этих чисел.

Математика «с нуля». Урок 21. Общий делитель. Наибольший общий делитель

Математика «с нуля». Урок 22. Общее кратное. Наименьшее общее кратное

НОД и НОК трех и более чисел

НОД (Факторизованный вид)
НОК (Факторизованный вид)
НОД (Числовое значение)
НОК (Числовое значение)


Что такое НОК?


НОК — наименьшее общее кратное. Такое число, на которое без остатка будет делится все заданные числа.


Например,  если заданные числа 2, 3, 5, то НОК=2*3*5=30


А если заданные числа  2,4,8, то НОК =8


что такое НОД?


НОД — наибольший общий делитель. Такое число, которым  можно разделить каждое из заданных чисел, без остатка.


Логично что  если заданные числа будут простыми, то НОД равен единице.


А если  заданны числа 2, 4, 8 то НОД равен 2.


НОД можно рассчитать по методу Евклида.


Расписывать его в общем виде не будем, а просто покажем решение на примере.


Заданы два числа 126 и 44. Найти НОД.


1. Делим 126 на 44 и находим остаток от деления  126=44*2+38. Остаток 38


2.Делим 44 на 38 и находим остаток. Он равен 6


3. Делим 38 на 6 и определим остаток. Остаток равен 2


4. Делим 6 на 2 и видим что он делится нацело, то есть с нулевым остатком.


Смотрим какое же было предыдущий остаток (на 3 вычислении). Видим что он равен 2


НОД этих двух чисел равен 2.


Альтернативный путь. Второй вариант который мы можем вам предложить  более нагляден и понятен , и позволит визуально увидеть чем отличается  НОК от НОД и как они высчитываются.


Для этого нам надо каждое число преобразовать в произведение сомножителей. Как это сделано в материале Простые множители. Теория чисел


Тогда если нам даны два числа вида


и


То НОД высчитывается как 


где min — минимальное значение  из всех значений степеней числа pn


а НОК  как 


где max — максимальное значение  из всех значений степеней числа pn


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


Поэтому легко ответить на вопрос чему равен НОД вот таких чисел  3,  25412, 3251, 7841, 25654, 7  ничего не вычисляя.


числа 3 и 7 взаимно простые, а следовательно НОД=1


Рассмотрим пример.


Даны три числа 24654, 25473 и 954


Каждое число  раскладывается в следующие множители


Или, если мы запишем в альтернативном виде


 


 


 


 


Теперь легко высчитать НОД по формуле


 


 


 


 


То есть НОД этих трех чисел равен трем


 


Ну а НОК можем вычислить аналогично, и он равен


 


 


Наш бот, поможет Вам вычислить НОД и НОК любых целых чисел, двух, трех или десяти.


 


Удобство нашего бота не только в легкости ввода, но и  в выведении результата.


 

Результат будет в двух видах, в виде  факторизации и в виде обычного численного решения.


 


Факторизация нам поможет увидеть точный результат, в случае если числа будут очень большие.


 


Ограничение только одно, кажое число не должно быть длиннее 15 символов


 


Удачных расчетов!


 

  • Нормальное интегральное распределение >>

nock / nock: библиотека имитации и ожиданий HTTP-сервера для Node.js

Библиотека имитации и ожиданий HTTP-сервера

для Node.js

Nock можно использовать для тестирования модулей, которые выполняют HTTP-запросы изолированно.

Например, если модуль выполняет HTTP-запросы к серверу CouchDB или делает HTTP-запросы к Amazon API, вы можете протестировать этот модуль изолированно.

Содержание

Как это работает?

Nock работает, переопределяя http.Запросить функцию . Кроме того, он переопределяет http.ClientRequest , чтобы покрыть модули, которые его напрямую используют.

Установить

 $ npm install --save-dev nock 

Поддержка версии узла

Последняя версия nock поддерживает все поддерживаемые в настоящее время версии узлов, см. График выпуска узлов

Вот список прошлых версий nock с поддержкой соответствующей версии узла

С

узел нок
0.10 до 8.x
0,11 до 8.x
0,12 до 8.x
4 до 9.x
5 до 8.x
6 до 10.x
7 до 9.x
8 до 11.x
9 до 9. x

Использование

В вашем тесте вы можете настроить свой имитирующий объект следующим образом:

 const nock = require ('nock')

const scope = nock ('https: // api.github.com ')
  .get ('/ репозиторий / атом / атом / лицензия')
  .reply (200, {
    лицензия: {
      ключ: 'мит',
      имя: 'Лицензия MIT',
      spdx_id: "MIT",
      URL: 'https://api.github.com/licenses/mit',
      node_id: 'MDc6TGljZW5zZTEz',
    },
  }) 

В этой настройке указано, что мы будем перехватывать каждый HTTP-вызов на https://api.github.com .

Он перехватит HTTPS-запрос GET на / repos / atom / atom / license , ответит
статус 200, а тело будет содержать (частичный) ответ в формате JSON.

ПРОЧИТАЙТЕ ЭТО! — О перехватчиках

Когда вы устанавливаете перехватчик для URL-адреса и этот перехватчик используется, он удаляется из списка перехватчиков.
Это означает, что вы можете перехватить 2 или более вызовов одного и того же URL-адреса и вернуть разные данные для каждого из них.
Это также означает, что вы должны настроить один перехватчик для каждого запроса, который вы собираетесь получить, иначе nock выдаст ошибку, потому что этот URL не присутствует в списке перехватчиков.
Если вы не хотите, чтобы перехватчики удалялись по мере их использования, вы можете использовать расширение.persist () метод.

Указание имени хоста

Имя хоста запроса может быть строкой или регулярным выражением.

 const scope = nock ('http://www.example.com')
  .get ('/ ресурс')
  .reply (200, 'домен сопоставлен') 
 const scope = nock (/example\.com/)
  .get ('/ ресурс')
  .reply (200, 'совпадение регулярного выражения домена') 

Примечание. Вы можете выбрать, включать или нет протокол в сопоставление имени хоста.

Указание пути

Путь запроса может быть строкой, регулярным выражением или функцией фильтра, и вы можете использовать любую команду HTTP.

Используя строку:

 const scope = nock ('http://www. example.com')
  .get ('/ ресурс')
  .reply (200, 'путь согласован') 

Использование регулярного выражения:

 const scope = nock ('http://www.example.com')
  .get (/ источник $ /)
  .reply (200, 'путь с использованием регулярного выражения согласован') 

Использование функции:

 const scope = nock ('http://www.example.com')
  .get (uri => uri.includes ('коты'))
  .reply (200, 'путь с использованием функции согласован') 

Определение тела запроса

Вы можете указать тело запроса для сопоставления в качестве второго аргумента в спецификациях get , post , put или delete .Допускается пять типов второго аргумента:

Строка : nock будет точно соответствовать строковому телу запроса с предоставленной строкой

 nock ('http://www.example.com')
  .post ('/ логин', 'имя пользователя = pgte и пароль = 123456')
  .reply (200, {id: '123ABC'}) 

Buffer : nock будет точно соответствовать строковому телу запроса с предоставленным буфером

 nock ('http://www. example.com')
  .post ('/ логин', Buffer.from ([0xff, 0x11]))
  .reply (200, {id: '123ABC'}) 

RegExp : nock будет проверять текст строкового запроса на соответствие предоставленному RegExp

 nock ('http: // www.example.com ')
  .post ('/ логин', / имя пользователя = \ w + / gi)
  .reply (200, {id: '123ABC'}) 

Объект JSON : nock будет точно соответствовать телу запроса с предоставленным объектом. Чтобы повысить гибкость, nock также поддерживает RegExp в качестве значения атрибута для ключей:

 nock ('http://www.example.com')
  .post ('/ логин', {имя пользователя: 'pgte', пароль: /.+/i})
  .reply (200, {id: '123ABC'}) 

Функция : nock будет оценивать функцию, предоставляющую объект тела запроса в качестве первого аргумента.Вернуть истину, если это следует считать совпадением:

 nock ('http://www.example.com')
  .post ('/ логин', body => body.username && body.password)
  .reply (200, {id: '123ABC'}) 

Если вам нужно выполнить частичное сопоставление для сложного вложенного тела запроса, вам следует взглянуть на библиотеки, такие как lodash. matches. Действительно, частичное совпадение может быть достигнуто как:

 nock ('http://www.example.com')
  .post ('/ user', _.matches ({address: {country: 'US'}}))
  .reply (200, {id: '123ABC'}) 

Указание строки запроса запроса

Нок понимает строки запроса.Параметры поиска могут быть включены как часть пути:

 nock ('http://example.com') .get ('/ users? Foo = bar') .reply (200) 

Вместо размещения всего URL-адреса вы можете указать часть запроса как объект:

 nock ('http://example.com')
  .get ('/ пользователи')
  .query ({имя: 'педро', фамилия: 'тейшейра'})
  .reply (200, {результаты: [{id: 'pgte'}]}) 

Nock поддерживает параметры запроса в стиле массива / объекта. Формат кодирования соответствует модулю запроса.

 nock ('http: // example.com ')
  .get ('/ пользователи')
  .запрос({
    имена: ['Алиса', 'Боб'],
    теги: {
      Алиса: ['админ', 'тестировщик'],
      bob: ['тестировщик'],
    },
  })
  . reply (200, {результаты: [{id: 'pgte'}]}) 

Может быть предоставлен экземпляр URLSearchParams .

 const params = новый URLSearchParams ({foo: 'bar'})

nock ('http://example.com') .get ('/') .query (параметры) .reply (200) 

Nock поддерживает передачу функции в запрос. Функция определяет, соответствует ли фактический запрос или нет.

 nock ('http://example.com')
  .get ('/ пользователи')
  .query (actualQueryObject => {
    // сравниваем с фактическим объектом запроса
    // возвращаем истину для совпавших
    // возвращаем false для несоответствия
    вернуть истину
  })
  .reply (200, {результаты: [{id: 'pgte'}]}) 

Чтобы издеваться над всем URL-адресом независимо от переданной строки запроса:

 nock ('http://example.com')
  .get ('/ пользователи')
  .query (истина)
  .reply (200, {результаты: [{id: 'pgte'}]}) 

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

 nock ('http://example.com', {encodedQueryParams: true})
  .get ('/ пользователи')
  .query ('foo% 5Bbar% 5D% 3Dhello% 20world% 21')
  .reply (200, {результаты: [{id: 'pgte'}]}) 

Указание ответов

Вы можете указать код статуса возврата для пути в первом аргументе ответа следующим образом:

 const scope = nock ('http://myapp.iriscouch.com') .get ('/ users / 1') .reply (404) 

Вы также можете указать тело ответа в виде строки:

 const scope = nock ('http: // www.google.com ')
  .получать('/')
  .reply (200, 'Привет от Google!') 

или как объект в кодировке JSON:

 const scope = nock ('http://myapp.iriscouch.com') .get ('/') .reply (200, {
  имя пользователя: 'pgte',
  электронная почта: '[email protected]',
  _id: '4324243fsd',
}) 

или даже в виде файла:

 const scope = nock ('http://myapp.iriscouch.com')
  .получать('/')
  .replyWithFile (200, __dirname + '/replies/user.json', {
    'Content-Type': 'application / json',
  }) 

Вместо объекта или буфера вы также можете передать обратный вызов для оценки значения тела ответа:

 const scope = nock ('http: // www. google.com ')
  .post ('/ эхо')
  .reply (201, (uri, requestBody) => requestBody) 

В Nock 11.x можно было вызвать .reply () с кодом состояния и
функция, которая возвращает массив, содержащий код состояния и тело. (Статус
код из массива будет иметь приоритет над кодом, переданным непосредственно в
ответ.) Это больше не разрешено. В Nock 12 и более поздних версиях либо вызовите .reply () с
код состояния и функция, которая возвращает тело, или вызывает ее с помощью одного
аргумент: функция, которая возвращает массив, содержащий как код состояния, так и
тело.

Асинхронная функция, которая получает обратный вызов при первой ошибке в качестве последнего аргумента, также работает:

 const scope = nock ('http://www.google.com')
  .post ('/ эхо')
  .reply (201, (uri, requestBody, cb) => {
    fs.readFile ('cat-poems.txt', cb) // Обратный вызов при первой ошибке
  }) 

В Nock 11 и более поздних версиях, если ошибка передается в функцию обратного вызова, Nock повторно выдаст ее как ошибку программиста.
В Nock 10 и ранее ошибка отправлялась в теле ответа с кодом состояния ответа HTTP 500.

Вы также можете вернуть код состояния и тело, используя всего одну функцию:

 const scope = nock ('http://www.google.com')
  .post ('/ эхо')
  .reply ((uri, requestBody) => {
    возвращаться [
      201,
      'ЭТО ОТВЕТНОЕ ТЕЛО',
      {header: 'value'}, // необязательные заголовки
    ]
  }) 

или воспользуйтесь функцией обратного вызова сначала с ошибкой, которая также получит код состояния:

 const scope = nock ('http://www.google.com')
  .post ('/ эхо')
  .reply ((uri, requestBody, cb) => {
    setTimeout (() => cb (null, [201, 'ЭТО ТЕЛО ОТВЕТА']), 1000)
  }) 

Стрим тоже работает:

 const scope = nock ('http: // www.google.com ')
  .get ('/ cat-poems')
  .reply (200, (uri, requestBody) => {
    вернуть fs.createReadStream ('cat-poems.txt')
  }) 
Доступ к исходному запросу и заголовкам

Если вы используете стиль обратного вызова ответа, вы можете получить доступ к исходному клиентскому запросу, используя this.req следующим образом:

 const scope = nock ('http://www.google.com')
  .get ('/ cat-poems')
  .reply (function (uri, requestBody) {
    console.log ('путь:', this.req.path)
    console.log ('заголовки:', это.req.headers)
    // ...
  }) 

Примечание. Не забудьте в этом случае использовать обычную функцию , поскольку стрелочные функции используют охватывающую область для этой привязки .

Ответ с ошибками

Вы можете ответить с такой ошибкой:

 nock ('http://www.google.com')
  .get ('/ cat-poems')
  .replyWithError ('случилось что-то ужасное') 

Разрешены также ответы об ошибках JSON:

 nock ('http://www.google.com') .get ('/ cat-poems').replyWithError ({
  message: 'случилось что-то ужасное',
  код: 'AWFUL_ERROR',
}) 

Примечание. Это приведет к возникновению события ошибки для объекта запроса , а не ответа.

Задание заголовков

Имена полей заголовка нечувствительны к регистру

В соответствии со спецификацией заголовков сообщений HTTP / 1.1 4.2, все заголовки сообщений нечувствительны к регистру, и, таким образом, внутри Nock для всех имен полей используются строчные буквы, даже если какая-то другая комбинация случаев была указана либо в фиктивной спецификации, либо в самих фиктивных запросах.

Указание заголовков запросов

Вы можете указать заголовки запроса следующим образом:

 const scope = nock ('http://www.example.com', {
  reqheaders: {
    авторизация: 'Basic Auth',
  },
})
  .получать('/')
  .ответ (200) 

Или вы можете использовать регулярное выражение или функцию для проверки значений заголовка. В
функции будет передано значение заголовка.

 const scope = nock ('http://www.example.com', {
  reqheaders: {
    'X-My-Headers': headerValue => headerValue.включает ('кошки'),
    "X-My-Awesome-Header": / Awesome / i,
  },
})
  .получать('/')
  .ответ (200) 

Если reqheaders не указан или если host не является его частью, Nock автоматически добавит значение host в заголовок запроса.

Если для фиксации не указаны заголовки запросов, Nock автоматически пропустит сопоставление заголовков запросов. Поскольку заголовок host является особым случаем, который может быть автоматически вставлен Nock, его сопоставление пропускается, если только он не был также , указанным в мнимом запросе.

Вы также можете заставить Nock отказывать в запросе, если присутствуют определенные заголовки:

 const scope = nock ('http://www.example.com', {
  badheaders: ['cookie', 'x-forwarded-for'],
})
  .получать('/')
  .ответ (200) 

При вызове с этой опцией Nock не будет соответствовать запросу, если присутствует какой-либо из badheaders .

Базовая аутентификация может быть указана следующим образом:

 const scope = nock ('http://www.example.com')
  .получать('/')
  .basicAuth ({пользователь: 'john', пароль: 'лань'})
  .ответить (200) 
Указание заголовков ответов

Вы можете указать заголовки ответа следующим образом:

 const scope = nock ('https://api.github.com')
  .get ('/ репозиторий / атом / атом / лицензия')
  .reply (200, {лицензия: 'MIT'}, {'X-RateLimit-Remaining': 4999}) 

Или вы можете использовать функцию для генерации значений заголовков. Функция будет
передал запрос, ответ и тело ответа (если доступно). Тело будет
быть либо буфером, либо потоком, либо неопределенным.

 const scope = nock ('http: // www.headdy.com ')
  .получать('/')
  .reply (200, 'Hello World!', {
    'Content-Length': (req, res, body) => body.length,
    ETag: () => `$ {Date.now ()}`,
  }) 
Заголовки ответов по умолчанию

Вы также можете указать заголовки ответов по умолчанию для всех ответов, например:

 const scope = nock ('http://www.headdy.com')
  .defaultReplyHeaders ({
    'X-Powered-By': 'Рельсы',
    'Content-Type': 'application / json',
  })
  .получать('/')
  .reply (200, 'Заголовки по умолчанию тоже должны быть') 

Или вы можете использовать функцию для генерации значений заголовков по умолчанию:

 const scope = nock ('http: // www.headdy.com ')
  .defaultReplyHeaders ({
    'Content-Length': (req, res, body) => body.length,
  })
  .получать('/')
  .reply (200, 'Заголовки по умолчанию тоже должны быть') 
Автоматическое включение заголовка длины содержимого

При использовании interceptor.reply () для установки тела ответа вручную вы можете
Content-Length заголовок рассчитывается автоматически.

 const scope = nock ('http://www.headdy.com')
  .replyContentLength ()
  .получать('/')
  .reply (200, {привет: 'мир'}) 

ПРИМЕЧАНИЕ: не работает с потоками или другими расширенными средствами указания
тело ответа.

Автоматическое включение заголовка даты

Вы можете автоматически добавить заголовок Date к вашему фиктивному ответу:

 const scope = nock ('http://www.headdy.com')
  .replyDate ()
  .получать('/')
  .reply (200, {привет: 'мир'}) 

Или предоставьте свой собственный Дата объект:

 const scope = nock ('http://www.headdy.com')
  .replyDate (новая дата (2015, 0, 1))
  .получать('/')
  .reply (200, {привет: 'мир'}) 

HTTP-глаголы

Nock поддерживает любые HTTP-команды и имеет удобные методы для HTTP-команд GET, POST, PUT, HEAD, DELETE, PATCH, OPTIONS и MERGE.

Вы можете перехватить любой HTTP-глагол, используя .intercept (path, verb [, requestBody [, options]]) :

 const scope = nock ('http://my.domain.com')
  .intercept ('/ путь', 'ПАТЧ')
  .ответ (304) 

Поддержка HTTP и HTTPS

По умолчанию nock предполагает HTTP. Если вам нужно использовать HTTPS, вы можете указать префикс https: // следующим образом:

 const scope = nock ('https://secure.my.server.com')
// ... 

Нестандартные порты

Вы можете указать нестандартный порт следующим образом:

 const scope = nock ('http: // my.server.com:8081 ') 

Повторить ответ n раз

Вы можете указать, сколько раз будет повторяться один и тот же ответ.

ПРИМЕЧАНИЕ: Если время запроса превышает указанное вами число, вы получите сообщение об ошибке перед очисткой этого перехватчика.

 nock ('http://zombo.com') .get ('/') .times (4) .reply (200, 'Хорошо')

http.get ('http://zombo.com/') // тело ответа "Ок"
http.get ('http://zombo.com/') // тело ответа "Ок"
http.get ('http://zombo.com/') // тело ответа "Ок"
http.get ('http://zombo.com/') // тело ответа "Хорошо"

// Этот код получит сообщение об ошибке:
// Nock: нет соответствия запросу
http.get ('http://zombo.com/')

// очищаем ваш перехватчик
nock.cleanAll ()

http.get ('http://zombo.com/') // настоящий ответ с результатом zombo.com 

Синтаксис сахара

 nock ('http://zombo.com') .get ('/') .once () .reply (200, 'Хорошо')
nock ('http://zombo.com') .get ('/') .twice () .reply (200, 'Хорошо')
nock ('http://zombo.com') .get ('/') .thrice () .reply (200, 'Хорошо') 

Чтобы повторять этот ответ, пока активен nock, используйте.сопротивляться().

Задержать ответ

Nock может моделировать задержку ответа, чтобы вы могли тестировать тайм-ауты, условия гонки и другие сценарии, связанные с синхронизацией.
Вы можете указать количество миллисекунд, на которое ваш ответ должен быть отложен.

 nock ('http://my.server.com')
  .получать('/')
  .delay (2000) // К заголовку ответа будет применена задержка в 2 секунды.
  .reply (200, ' ') 

delay (1000) — это псевдоним для delayConnection (1000).delayBody (0)
delay ({head: 1000, body: 2000}) — это псевдоним для delayConnection (1000) .delayBody (2000)
Оба из них подробно описаны ниже.

Задержка подключения

Вы можете указать количество миллисекунд, в течение которых ваше соединение должно находиться в режиме ожидания, прежде чем оно начнет получать ответ.

Чтобы смоделировать тайм-аут сокета, укажите в запросе значение, превышающее значение тайм-аута.

 nock ('http: // my.server.com ')
  .получать('/')
  .delayConnection (2000) // 2 секунды
  .reply (200, ' ')

req = http.request ('http://my.server.com', {тайм-аут: 1000}) 

Nock генерирует события тайм-аута почти сразу, сравнивая запрошенную задержку соединения с параметром тайм-аута, переданным в http.request () или http.ClientRequest # setTimeout () .
Это позволяет вам тестировать тайм-ауты без использования фальшивых таймеров или замедления ваших тестов.
Если клиент выбирает , а не , выполните действие (например,грамм. прервать запрос), запрос и ответ продолжатся в обычном режиме по истечении реального времени.

Технические характеристики

После события 'finish' , генерируемого ClientRequest , Nock будет ждать следующей итерации цикла событий, прежде чем проверять, был ли запрос прерван.
На этом этапе любое значение задержки соединения сравнивается с любой настройкой тайм-аута запроса, и «тайм-аут» выдается, когда это необходимо, из сокета и объектов запроса.Затем таймер тайм-аута узла регистрируется с любым значением задержки соединения для задержки в реальном времени перед повторной проверкой того, был ли запрос прерван, и запрос «ответ» испускает запрос.

Аналогичный метод, .socketDelay () был удален в версии 13. Считалось, что наличие двух таких тонких методов сбивает с толку.
Обсуждение можно найти по адресу https://github.com/nock/nock/pull/1974.

Задержка тела ответа

Вы можете указать количество миллисекунд, на которое следует задержать тело ответа.
Это время между получением заголовков и началом приема тела.

 nock ('http://my.server.com')
  .получать('/')
  .delayBody (2000) // 2 секунды
  .reply (200, ' ') 
Технические характеристики

После «ответа» , отправленного ClientRequest ,
Нок зарегистрирует таймер тайм-аута со значением задержки тела, чтобы задержать реальное время перед тем, как IncomingMessage отправит свои первые «данные» или событие «конец» .

Цепь

Вы можете связать поведение следующим образом:

 const scope = nock ('http://myapp.iriscouch.com')
  .get ('/ пользователи / 1')
  .ответ (404)
  .post ('/ users', {
    имя пользователя: 'pgte',
    электронная почта: '[email protected]',
  })
  .reply (201, {
    ок: правда,
    id: '123ABC',
    rev: '946B7D1C',
  })
  .get ('/ users / 123ABC')
  .reply (200, {
    _id: '123ABC',
    _rev: '946B7D1C',
    имя пользователя: 'pgte',
    электронная почта: '[email protected]',
  }) 

Область фильтрации

Вы можете фильтровать область действия (протокол, домен или порт) nock с помощью функции.https: \ / \ / api [0-9] *. dropbox.com/.test(scope),
})
.get (‘/ 1 / metadata / auto / Photos? include_deleted = false & list = true’)
.ответ (200)

Фильтрация условной области

Вы также можете выбрать фильтрацию области на основе вашей системной среды (или любого внешнего фактора). Функция фильтрации принимается в поле условно аргумента options .

Это может быть полезно, если вы хотите, чтобы применялись только определенные области в зависимости от того, как выполняются ваши тесты.&] * / g, ‘пароль = XXX’)
.get (‘/ users / 1? password = XXX’)
.reply (200, ‘пользователь’)

Или вы можете использовать функцию:

 const scope = nock ('http://api.myservice.com')
  .filteringPath (путь => '/ ABC')
  .get ('/ ABC')
  .reply (200, 'пользователь') 

Обратите внимание, что scope.filteringPath не является кумулятивным: его следует использовать только один раз для каждой области.

Фильтрация тела запроса

Вы также можете фильтровать тело запроса на основе функции.

Это может быть полезно, например, если у вас есть случайные или зависящие от времени данные в теле запроса.&] * / g, ‘пароль = XXX’)
.post (‘/ users / 1’, ‘data = ABC и пароль = XXX’)
.reply (201, ‘ОК’)

Или вы можете использовать функцию для преобразования тела:

 const scope = nock ('http://api.myservice.com')
  .filteringRequestBody (body => 'ABC').
  .post ('/', 'ABC').
  .reply (201, 'ОК') 

Если вы не хотите сопоставлять тело запроса, вы должны опустить аргумент body из функции метода:

 const scope = nock ('http://api.myservice.com')
  .post ('/ some_uri') // без основного аргумента
  .ответить (200, 'ОК') 

Соответствие заголовков запросов

Если вам нужно сопоставлять запросы только при совпадении определенных заголовков запросов, вы можете это сделать.

 const scope = nock ('http://api.myservice.com')
  .matchHeader ('принять', 'приложение / json')
  .получать('/')
  .reply (200, {
    данные: 'привет мир',
  }) 

Вы также можете использовать регулярное выражение для тела заголовка.

 const scope = nock ('http://api.myservice.com')
  .matchHeader ('Пользователь-агент', /Mozilla\/.*/)
  .получать('/')
  .reply (200, {
    данные: 'привет мир',
  }) 

Вы также можете использовать функцию для тела заголовка.

 const scope = nock ('http://api.myservice.com')
  .matchHeader ('длина содержимого', значение => значение> = 1000)
  .получать('/')
  .reply (200, {
    данные: 'привет мир',
  }) 

Дополнительные запросы

По умолчанию ожидается, что каждый фиктивный запрос будет выполнен ровно один раз, и пока он не появится в scope.pendingMocks () и scope.isDone () вернет false (см. Ожидания). Во многих случаях это нормально, но в некоторых (особенно в коде настройки перекрестного тестирования) полезно иметь возможность имитировать запрос, который может или не может произойти.Вы можете сделать это с помощью опционально () . Необязательные запросы потребляются так же, как обычные после сопоставления, но они не отображаются в pendingMocks () , а isDone () вернет true для областей с только необязательными ожидающими запросами.

 const example = nock ('http://example.com')
example.pendingMocks () // []
example.get ('/ pathA'). reply (200)
example.pendingMocks () // ["ПОЛУЧИТЬ http://example.com:80/path"]

// ... После запроса на example.com/pathA:
example.pendingMocks () // []

пример.получить ('/ путьB'). необязательно (). ответ (200)
example.pendingMocks () // []

// Вы также можете передать логический аргумент в `optionally ()`. Этот
// полезно, если вы хотите условно сделать фиктивный запрос
// по желанию.
const getMock = необязательно =>
  example.get ('/ pathC'). необязательно (необязательно) .reply (200)

getMock (правда)
example.pendingMocks () // []
getMock (ложь)
example.pendingMocks () // ["ПОЛУЧИТЬ http://example.com:80/pathC"] 

Разрешить

разблокированных запросов на поддельном имени хоста

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

 const scope = nock ('http: // my.существующий.service.com ', {allowUnmocked: true})
  .get ('/ мой / URL')
  .reply (200, 'ОК!')

// GET / my / url => проходит через нок
// GET / other / url => фактически делает запрос к серверу 

Примечание. При применении {allowUnmocked: true} , если запрос сделан на реальный сервер, перехватчик не удаляется.

Ожидания

Каждый раз, когда выполняется HTTP-запрос для имитируемой области, Нок ожидает найти для него обработчик. В противном случае выдаст ошибку.

Вызов nock () возвращает область, которую можно подтвердить, вызвав scope.done () . Это будет утверждать, что все указанные вызовы в этой области были выполнены.

Пример:

 const scope = nock ('http://google.com')
  .получать('/')
  .reply (200, 'Привет из Google!')

// делаем кое-что

setTimeout (() => {
  // Выдает ошибку утверждения, если в это время было задано "GET http://google.com"
  // Не выполнена.
  scope.done ()
}, 5000) 

.isDone ()

Вы можете вызвать isDone () с одним ожиданием, чтобы определить, было ли оно оправдано:

 const scope = nock ('http: // google.com '). get (' / '). reply (200)

scope.isDone () // вернет false 

Он также доступен в глобальном масштабе, который определит, оправдались ли все ожидания:

.cleanAll ()

Вы можете очистить все подготовленные макеты (может быть полезно для очистки некоторого состояния после неудачного теста) следующим образом:

.abortPendingRequests ()

Вы можете прервать все текущие ожидающие запросы следующим образом:

 nock.abortPendingRequests () 

.persist ()

Вы можете сохранить все перехватчики для области видимости, позвонив по номеру .persist () на нем:

 const scope = nock ('http://example.com')
  .сопротивляться()
  .получать('/')
  .reply (200, 'Сохраняется до конца') 

Обратите внимание, что, хотя постоянная область всегда будет перехватывать запросы, она считается «выполненной» после первого перехвата.

Если вы хотите прекратить сохранение отдельного сохраняемого имита, вы можете вызвать persist (false) :

 const scope = nock ('http://example.com') .persist () .get ('/') .reply (200, 'хорошо')

// Проведите несколько тестов...

scope.persist (ложь) 

Вы также можете использовать nock.cleanAll () , который удаляет все моки, включая постоянные моки.

Чтобы указать точное количество раз, которое nock должен повторять ответ, используйте .times ().

.pendingMocks ()

Если область действия не создана, вы можете проверить ее, чтобы определить, какие из них еще не завершены, используя функцию scope.pendingMocks () :

 if (! Scope.isDone ()) {
  console.error ('ожидающие проверки:% j', scope.pendingMocks ())
} 

Он также доступен в глобальном масштабе:

 console.error ('ожидающие проверки:% j', nock.pendingMocks ()) 

.activeMocks ()

Вы можете увидеть каждый макет, который в настоящее время активен (т. Е. Потенциально может отвечать на запросы) в области, используя scope.activeMocks () . Мок активен, если он ожидает рассмотрения, необязателен, но еще не завершен или сохраняется. Моки, которые перехватили их запросы и больше ничего не делают, — единственные имитации, которые здесь не появятся.

Вам, вероятно, не нужно использовать это — в основном он существует как механизм для воссоздания предыдущего (теперь измененного) поведения pendingMocks () .

 console.error ('активные mocks:% j', scope.activeMocks ()) 

Он также доступен в глобальном масштабе:

 console.error ('активные mocks:% j', nock.activeMocks ()) 

.isActive ()

Иногда в ваших тестах может потребоваться отключить перехватчик с носком.
После деактивации нок необходимо повторно активировать, чтобы он работал.Вы можете проверить, активен ли перехватчик nock, используя nock.isActive () .
Образец:

 if (! Nock.isActive ()) {
  nock.activate ()
} 

Восстановление

Вы можете восстановить нормальное разблокированное поведение HTTP-перехватчика, позвонив по номеру:

примечание 1 : восстановление не очищает список перехватчиков. Используйте nock.cleanAll (), если вы ожидаете, что список перехватчиков будет пустым.

note 2 : restore также удалит сам http-перехватчик.Вам нужно запустить nock.activate (), чтобы повторно активировать http-перехватчик. Без повторной активации nock не будет перехватывать звонки.

Активация

Только в тех случаях, когда nock был деактивирован с помощью nock.restore (), вы можете повторно активировать HTTP-перехватчик, чтобы начать перехват HTTP-вызовов, используя:

note : Чтобы проверить, активен или неактивен перехватчик HTTP nock, используйте nock.isActive ().

Отключение Nock Off (экспериментально!)

Вы можете полностью обойти Nock, установив для переменной среды NOCK_OFF значение "true" .

Таким образом, ваши тесты могут попасть на реальные серверы, просто включив эту переменную окружения.

 $ NOCK_OFF = истинный узел my_test.js 

Включение / отключение реальных HTTP-запросов

По умолчанию любые запросы к хосту, который не является имитируемым, будут выполняться нормально. Если вы хотите заблокировать эти запросы, nock позволяет это сделать.

Запросы на отключение

Для отключения реальных http запросов.

Итак, если вы попытаетесь запросить любой хост, не «заблокированный», он выдаст NetConnectNotAllowedError .

 nock.disableNetConnect ()
const req = http.get ('http://google.com/')
req.on ('ошибка', err => {
  console.log (ошибка)
})
// Возвращенный `http.ClientRequest` выдаст событие ошибки (или выбросит, если вы его не слушаете)
// Этот код регистрирует NetConnectNotAllowedError с сообщением:
// Nock: запрещено сетевое соединение для "google.com:80" 

Запросы включения

Для включения любых реальных HTTP-запросов (поведение по умолчанию):

Вы можете разрешить реальные HTTP-запросы для определенных имен хостов, указав строку или регулярное выражение для имени хоста или функцию, которая принимает имя хоста и возвращает истину или ложь:

 // Использование строки
нок.enableNetConnect ('amazon.com')

// Или RegExp
nock.enableNetConnect (/ (амазонка | github) \. com /)

// Или функция
nock.enableNetConnect (
  host => host.includes ('amazon.com') || host.includes ('github.com')
)

http.get ('http://www.amazon.com/')
http.get ('http://github.com/')

http.get ('http://google.com/')
// Это вызовет NetConnectNotAllowedError с сообщением:
// Nock: запрещено сетевое соединение для "google.com:80" 

Типичный вариант использования при тестировании локальных конечных точек — отключить все, кроме localhost, а затем добавить дополнительные ноки для внешних запросов:

 нок.disableNetConnect ()
// Разрешить соединения localhost, чтобы мы могли тестировать локальные маршруты и имитировать серверы.
nock.enableNetConnect ('127.0.0.1') 

Сброс NetConnect

Когда вы закончите тест, вы, вероятно, захотите вернуть все в норму:

 nock.cleanAll ()
nock.enableNetConnect () 

Запись

Это классная функция:

Догадаться, что такое HTTP-вызовы, — беспорядок, особенно если вы вводите nock в свои уже закодированные тесты.

В тех случаях, когда вы хотите имитировать существующую живую систему, вы можете записывать и воспроизводить HTTP-вызовы следующим образом:

 nock.recorder.rec ()
// Некоторые HTTP-вызовы происходят и код блокировки необходим для имитации
// эти вызовы будут выведены на консоль 

Запись основана на перехвате реальных запросов и ответов, а затем их сохранении для дальнейшего использования.

Чтобы остановить запись, необходимо позвонить по номеру nock.restore () , и запись остановится.

ВНИМАНИЕ !: когда запись включена, nock не проверяет, и никакие mocks не будут включены.Не забудьте выключить запись, прежде чем пытаться использовать какие-либо имитации в своих тестах.

dont_print опция

Если вы просто хотите записать сгенерированный код в переменную в виде массива, вы можете использовать:

 nock.recorder.rec ({
  dont_print: правда,
})
// ... некоторые HTTP-вызовы
константа nockCalls = nock.recorder.play () 

nockCalls var будет содержать массив строк, представляющих сгенерированный код, который вам нужен.

Скопируйте и вставьте этот код в свои тесты, настройте по своему желанию, и готово! Вы можете позвонить по номеру nock.Recorder.clear () , чтобы удалить уже записанные вызовы из массива, который возвращает nock.recorder.play () .

(помните, что вы должны делать это по одному тесту за раз).

output_objects option

Если вы хотите сгенерировать код самостоятельно или использовать тестовые данные каким-либо другим способом, вы можете передать опцию output_objects в rec :

 nock.recorder.rec ({
  output_objects: истина,
})
// ... некоторые HTTP-вызовы
const nockCallObjects = нок.рекордер.play () 

Возвращенные объекты вызова имеют следующие свойства:

  • scope — объем вызова, включая протокол и нестандартные порты (например, 'https://github.com:12345' )
  • method — HTTP-глагол вызова (например, 'GET' )
  • путь — путь вызова (например, '/ pgte / nock' )
  • body — тело вызова, если есть
  • status — HTTP-статус ответа (e.грамм. 200 )
  • ответ — тело ответа, которое может быть JSON, строкой, шестнадцатеричной строкой, представляющей двоичные буферы, или массивом таких шестнадцатеричных строк (при обработке кодированного содержимого в заголовке ответа)
  • заголовки — заголовки ответа
  • reqheader — заголовки запроса

Если вы сохраните это как файл JSON, вы можете загрузить их напрямую через nock.load (путь) . Затем вы можете постобработать их перед использованием в тестах.Например, чтобы добавить фильтрацию тела запроса (здесь показано исправление меток времени, чтобы они соответствовали тем, которые были записаны во время записи):

 nocks = nock.load (pathToJson)
nocks.forEach (function (nock) {
  nock.filteringRequestBody = (body, aRecordedBody) => {
    if (typeof body! == 'строка' || typeof aRecordedBody! == 'строка') {
      вернуть тело
    }

    const loadedBodyResult = /timestamp:(( [0-9 ]+)/.exec(aRecordedBody)
    if (loadedBodyResult) {
      const loadedTimestamp = loadedBodyResult [1]
      вернуть тело.заменять(
        / (отметка времени): ([0-9] +) / г,
        функция (совпадение, ключ, значение) {
          клавиша возврата + ':' + loadedTimestamp
        }
      )
    } еще {
      вернуть тело
    }
  }
}) 

В качестве альтернативы, если вам нужно предварительно обработать захваченные определения выступов перед
используя их (например, чтобы добавить фильтрацию области), вы можете использовать nock.loadDefs (path)
и nock.define (nockDefs) . Здесь показана фильтрация области для узла Dropbox.
модуль, который постоянно меняет поддомен, на который он отправляет запросы:

 // Предварительная обработка определений узловых точек, поскольку фильтрация области видимости должна быть определена до определения узловых точек (из-за ее очень хакерской природы).https: \ / \ / api [0-9] *. dropbox.com/.test(scope),
  }
})

// Загружаем насадки из предварительно обработанных определений.
const nocks = nock.define (nockDefs) 

enable_reqheaders_recording option

Заголовки запросов на запись по умолчанию считаются больше проблемой, чем того стоит, поскольку некоторые из них зависят от метки времени или других значений, которые могут измениться после записи тестов, что приводит к сложной постобработке записанных тестов. Таким образом, по умолчанию заголовки запроса не записываются.

Подлинные варианты использования для записи заголовков запросов (например, проверка авторизации) можно обрабатывать вручную или с помощью enable_reqheaders_recording в опциях recorder.rec () .

 nock.recorder.rec ({
  dont_print: правда,
  output_objects: истина,
  enable_reqheaders_recording: истина,
}) 

Обратите внимание, что даже если включена запись заголовков запросов, Nock никогда не будет записывать заголовки user-agent . пользовательский агент. Значения изменяются вместе с версией узла и базовой операционной системы, и поэтому они бесполезны для сопоставления, поскольку все, что они могут указать, — это то, что пользовательский агент не тот, который использовался для записи тестов.

лесозаготовка опция

Nock будет печатать с использованием console.log по умолчанию (при условии, что dont_print равно false ). Если в , регистрирующий , передается другая функция, nock отправит строку журнала (или объект, при использовании output_objects ) этой функции. Вот простой пример.

 const appendLogToFile = content => {
  fs.appendFile ('record.txt', содержимое)
}
nock.recorder.rec ({
  ведение журнала: appendLogToFile,
}) 

use_separator опция

По умолчанию nock оборачивает свой вывод разделительной строкой <<<<<< - вырезать здесь - >>>>>> до и после всего, что он печатает, будь то на консоль или заданная пользовательская функция журнала с опцией регистрации .

Чтобы отключить это, установите для use_separator значение false.

 nock.recorder.rec ({
  use_separator: ложь,
}) 

.removeInterceptor ()

Это позволяет удалить конкретный перехватчик. Это может быть либо экземпляр перехватчика, либо параметры URL-адреса. Это полезно, когда есть список общих перехватчиков, совместно используемых тестами, когда отдельный тест требует, чтобы один из общих перехватчиков вел себя по-разному.

Примеры:

 нок.removeInterceptor ({
  имя хоста: 'localhost',
  путь: '/ mockedResource',
}) 
 nock.removeInterceptor ({
  имя хоста: 'localhost',
  путь: '/ логин',
  метод: 'POST',
  proto: 'https',
}) 
 константный перехватчик = nock ('http://example.org') .get ('somePath')
nock.removeInterceptor (перехватчик) 

События

Осциллограф генерирует следующие события:

  • emit ('запрос', функция (req, interceptor, body))
  • emit ('ответил', функция (req, interceptor))

Глобальное событие отсутствия матча

Вы также можете прослушивать события отсутствия совпадений, например:

 нок.emitter.on ('нет совпадения', req => {}) 

Носик спины

Устройство поддержки записи и воспроизведения.

Настройка

Перед использованием необходимо указать каталог приборов, например:

В вашем помощнике по тестированию

 const nockBack = require ('nock'). Назад

nockBack.fixtures = '/ путь / к / приспособлениям /'
nockBack.setMode ('запись') 
Опции
  • nockBack.fixtures : путь к каталогу устройств
  • nockBack.setMode () : используемый режим

Использование

По умолчанию, если прибор не существует, nockBack создаст новый прибор и сохранит записанный результат.
для тебя. При следующем запуске теста, если прибор существует, он будет загружен.

контекст функции обратного вызова будет иметь свойство области действия для доступа ко всем загруженным
прицелы.

 const nockBack = require ('nock'). Назад
const request = require ('запрос')
nockBack.setMode ('запись')

nockBack.fixtures = __dirname + '/ nockFixtures' // это нужно установить только один раз в вашем помощнике по тестированию

// запись фикстуры
nockBack ('zomboFixture.json', nockDone => {
  request.get ('http://zombo.com', (err, res, body) => {
    nockDone ()

    // использование созданного приспособления
    nockBack ('zomboFixture.json', function (nockDone) {
      http.get ('http://zombo.com/') .end () // тело ответа "ОК"

      this.assertScopesFinished () // выдает исключение, если все ноки в фикстуре не были выполнены
      http.get ('http://zombo.com/') .end () // выдает исключение, потому что у someFixture.json был только один вызов

      nockDone () // сюда никогда не попадает
    })
  })
}) 

Если в ваших тестах используются обещания, используйте nockBack следующим образом:

 вернуть nockBack ('promiseFixture.json'). Then (({nockDone, context}) => {
  // выполняем ваши тесты, возвращая обещание, и связываем его с
  // `.then (nockDone)`
}) 
Опции

В качестве необязательного второго параметра вы можете передать следующие параметры

  • до : функция предварительной обработки, вызывается перед nock.определить
  • после : функция постобработки, вызывается после nock.define
  • afterRecord : функция постобработки, вызывается после записи. Передается массив записанных областей действия и должен возвращать неповрежденный массив, измененную версию массива или, если требуется настраиваемое форматирование, строковую версию массива для сохранения в прибор
  • записывающее устройство : настраиваемые параметры для передачи записывающему устройству
Пример
 function prepareScope (scope) {
  сфера.filteringRequestBody = (body, aRecordedBody) => {
    if (typeof body! == 'строка' || typeof aRecordedBody! == 'строка') {
      вернуть тело
    }

    const loadedBodyResult = /timestamp:(( [0-9 ]+)/.exec(aRecordedBody)
    if (loadedBodyResult) {
      const loadedTimestamp = loadedBodyResult [1]
      вернуть body.replace (
        / (отметка времени): ([0-9] +) / г,
        (совпадение, ключ, значение) => `$ {ключ}: $ {recordTimestamp}`
      )
    } еще {
      вернуть тело
    }
  }
}

nockBack ('exampleFixture.json ', {before: prepareScope}, nockDone => {
  request.get ('http://example.com', function (err, res, body) {
    // делаем ваши тесты
    nockDone ()
  })
}) 

Режимы

Для установки режима вызовите nockBack.setMode (mode) или запустите тесты с установленной переменной среды NOCK_BACK_MODE перед загрузкой nock. Если режим необходимо изменить программно, допустимо следующее: nockBack.setMode (nockBack.currentMode)

  • wild: все запросы уходят в интернет, ничего не воспроизводится, ничего не записывает

  • dryrun: по умолчанию, использовать записанные ноки, разрешить http-вызовы, ничего не записывать, полезно для написания новых тестов

  • запись: использовать записанные ноки, записывать новые ноки

  • Блокировка

    : использовать записанные ноки, отключает все HTTP-вызовы, даже если нет ноков, не записывает

Общие проблемы

«Нет совпадений для ответа» при использовании ответов с ошибками

Got автоматически повторяет неудачные запросы дважды.Это означает, что если у вас есть
test, который имитирует ответ 4xx или 5xx, got немедленно перевыпустит его. В
в этот момент макет будет использован, а второй запрос выдаст ошибку
с Nock: не соответствует запросу .

То же верно и для .replyWithError () .

Добавление {retry: 0} к , получившим вызовы , отключит повторные попытки, например:

 await got ('http: //example.test/', {retry: 0}) 

Если вам нужно сделать это во всех ваших тестах, вы можете создать модуль
got_client.js , который экспортирует собственный полученный экземпляр:

 const got = require ('получил')

module.exports = got.extend ({retry: 0}) 

Вот как это делается в самом Ноке (см. №1523).

Axios

Чтобы использовать Nock с Axios, вам может потребоваться настроить Axios для использования Node.
адаптер, как в примере ниже:

 импортировать axios из 'axios'
импортировать нок из нока
import test from 'ava' // Вы можете использовать любую среду тестирования.

// Если вы используете jsdom, axios по умолчанию будет использовать адаптер XHR, который
// не может быть перехвачен nock.Итак, настройте axios для использования адаптера узла.
//
// Рекомендации:
// https://github.com/nock/nock/issues/699#issuecomment-272708264
// https://github.com/axios/axios/issues/305
axios.defaults.adapter = требуется ('axios / lib / adapters / http')

test ('может получить тестовый ответ', async t => {
  // Устанавливаем фиктивный запрос.
  const scope = nock ('http: // локальный хост')
    .get ('/ тест')
    .reply (200, 'тестовый ответ')

  // Делаем запрос. Обратите внимание, что имя хоста должно точно соответствовать переданному
  // в `nock ()`.В качестве альтернативы вы можете установить axios.defaults.host = 'http: // localhost'
  // и запускаем `axios.get ('/ test')`.
  ждать axios.get ('http: // localhost / test')

  // Подтверждаем, что ожидаемый запрос был сделан.
  scope.done ()
}) 

Проблемы с памятью в Jest

Проблем с памятью можно избежать, вызывая nock.restore () после каждого набора тестов.
Один из основных принципов Jest — изолированное выполнение тестов.
Он делает это, манипулируя кешем модулей Node способом, который конфликтует с тем, как Nock monkey исправляет встроенные модули http и https .Связанная проблема с более подробной информацией.

Отладка

Nock использует отладку , поэтому просто запустите с переменной окружения DEBUG , установленной на nock. * .

 пользователь @ local $ DEBUG = nock. * Node my_test.js 

Каждый шаг в процессе сопоставления регистрируется таким образом и может быть полезен при определении, почему запрос не был перехвачен Nock.

Например, следующее показывает, что сопоставление не удалось, потому что в запросе был дополнительный параметр поиска.

 nock ('http://example.com') .get ('/') .query ({foo: 'bar'}). Reply ()

ожидание получил ('http://example.com/?foo=bar&baz=foz') 
 пользователь @ local $ DEBUG = nock.scope: example.com node my_test.js
...
nock.scope: example.com Запросы перехватчика: {"foo": "bar"} + 1 мс
nock.scope: example.com Запросы запросов: {"foo": "bar", "baz": "foz"} + 0 мс
nock.scope: не удалось сопоставить запрос example.com + 0 мс 

Содействие

Спасибо за желание внести свой вклад! Взгляните на наше Руководство по участию, чтобы узнать о наших соглашениях о сообщениях о фиксации и о том, как запускать тесты.

Обратите внимание, что этот проект выпущен с Кодексом поведения авторов.
Участвуя в этом проекте, вы соглашаетесь соблюдать его условия.

Авторы

Спасибо этим замечательным людям (смайлик):

Этот проект соответствует спецификации всех участников. Любые пожертвования приветствуются!

Спонсоры

Поддержите этот проект, став спонсором. Здесь будет отображаться ваш логотип со ссылкой на ваш веб-сайт. [Стать спонсором]

Лицензия

MIT

Авторские права (c) 2011–2019 Педро Тейшейра и другие участники.

рекомендаций по тестированию Node.js и JavaScript (2020 г.) | Автор: Йони Голдберг

✅ Do: Кодирование ваших тестов в декларативном стиле позволяет читателю мгновенно получить представление, не затрачивая ни единого цикла между мозгом и процессором. Когда вы пишете императивный код, наполненный условной логикой, читатель впадает в напряженное умственное состояние. В этом смысле кодируйте ожидание на человекоподобном языке, декларативном стиле BDD с использованием , ожидайте или , следует и не используя собственный код.Если Chai & Jest не включает желаемое утверждение и оно хорошо воспроизводимо, рассмотрите возможность расширения Jest matcher (Jest) или написания специального плагина Chai

❎ В противном случае: Команда напишет меньше тестов и украсит надоедливые утверждения с помощью .skip ()

😕 Пример антипаттерна: Читатель должен пролистать не такой короткий и императивный код только для того, чтобы ознакомиться с историей теста

: Пример правильного выполнения: Быстрый просмотр следующего декларативного теста

✅ Do: Набор подключаемых модулей ESLint был создан специально для проверки шаблонов кода тестов и обнаружения проблем.Например, eslint-plugin-mocha будет предупреждать, когда тест написан на глобальном уровне (не является сыном оператора describe ()) или когда тесты пропускаются, что может привести к ложному убеждению, что все тесты пройдены. Точно так же eslint-plugin-jest может, например, предупреждать, когда тест вообще не имеет утверждений (ничего не проверяет)

❎ В противном случае: Если вы увидите, что 90% покрытия кода и 100% зеленые тесты заставят ваше лицо выглядеть большим улыбайтесь только до тех пор, пока не поймете, что многие тесты ни на что не претендуют, а многие наборы тестов просто пропущены.Надеюсь, вы ничего не развернули, основываясь на этом ложном наблюдении.

Пример антипаттерна: Тестовый пример, полный ошибок, к счастью, все они обнаруживаются Линтерсом

✅ Do: Тестирование внутренних компонентов почти всегда требует огромных затрат ничего такого. Если ваш код / ​​API дает правильные результаты, стоит ли вам потратить следующие 3 часа на тестирование КАК он работает внутри компании, а затем поддерживать эти хрупкие тесты? Всякий раз, когда проверяется общедоступное поведение, неявно проверяется и частная реализация, и ваши тесты не работают, только если есть определенная проблема (например,грамм. неправильный вывод). Этот подход также называется поведенческим тестированием. С другой стороны, если вы протестируете внутреннее устройство (подход белого ящика) — ваш фокус смещается с планирования результата компонента на мельчайшие детали, и ваш тест может сломаться из-за незначительных рефакторингов кода, хотя результаты в порядке — это значительно увеличивает обслуживание burden

❎ В противном случае: Ваш тест ведет себя как ребенок, который плачет волком: громко выкрикивает ложноположительные крики (например, тест не проходит из-за изменения имени частной переменной).Неудивительно, что вскоре люди начнут игнорировать уведомления CI до тех пор, пока однажды настоящая ошибка не будет проигнорирована …

😕 Пример антипаттерна: Тестовый пример — это тестирование внутренних компонентов без уважительной причины

✅ Do: Тестовые двойники — это необходимое зло, потому что они связаны с внутренними компонентами приложения, но некоторые из них имеют огромную ценность (прочтите здесь напоминание о тестовых двойниках: моки против заглушек против шпионов). Однако различные методы не родились равными: некоторые из них, шпионы и заглушки, сосредоточены на проверке требований, но, как неизбежный побочный эффект , они также слегка касаются внутренних компонентов.Моки, напротив, ориентированы на тестирование внутренних компонентов — это приводит к огромным накладным расходам, как объясняется в пункте «Придерживайтесь тестирования черного ящика».

Перед использованием тестовых двойников задайте очень простой вопрос: я использую его для проверки функциональности, которая появляется или может появиться в документе с требованиями? Если нет, то это запах тестирования методом белого ящика.

Например, если вы хотите проверить, что ваше приложение ведет себя разумно, когда платежная служба не работает, вы можете заглушить платежную службу и вызвать ответ «Нет ответа», чтобы убедиться, что тестируемая единица возвращает правильное значение.Это проверяет поведение нашего приложения / ответ / результат при определенных сценариях. Вы также можете использовать шпион, чтобы утверждать, что электронное письмо было отправлено, когда эта служба не работает — это снова поведенческая проверка, которая, вероятно, появится в документе с требованиями («Отправить электронное письмо, если не удалось сохранить платеж»). С другой стороны, если вы имитируете службу платежей и убедитесь, что она вызывается с правильными типами JavaScript, тогда ваш тест будет сосредоточен на внутренних вещах, которые не имеют ничего общего с функциональностью приложения и, вероятно, будут часто меняться

2 В противном случае: Любой рефакторинг кода требует поиска всех имитаций в коде и соответствующего обновления.Тесты становятся обузой, а не полезным другом

😕 Пример анти-паттерна: Моки фокусируются на внутреннем устройстве

☺️ Делаем это правильно Пример: шпионов сосредоточены на проверке требований, но в качестве побочного эффекта неизбежно трогают к внутреннему устройству

✅ Do: Часто производственные ошибки обнаруживаются при очень специфических и неожиданных входных данных — чем более реалистичны входные данные теста, тем больше шансов обнаружить ошибки на раннем этапе. Используйте специальные библиотеки, такие как Faker, для создания псевдореальных данных, которые напоминают по разнообразию и форме производственные данные.Например, такие библиотеки будут генерировать случайные, но реалистичные номера телефонов, имена пользователей, кредитные карты, названия компаний и даже текст «lorem ipsum». Подумайте даже об импорте реальных данных из производственной среды и использовании их в тестах. Хотите перейти на новый уровень? см. следующий пункт (тестирование на основе свойств)

В противном случае: Все ваши тесты разработки будут ошибочно казаться зелеными, когда вы используете синтетические входные данные, такие как «Foo», но затем производство может стать красным, когда хакер передает неприятную строку вроде « @ 3e2ddsf.## ’1 fdsfds. fds432 AAAA ”

😕 Пример антипаттерна: набор тестов, который проходит из-за нереалистичных данных

ExampleПример правильного выполнения: случайный выбор реалистичного ввода

Получите более 10 часов курса по качеству Node.js и тестирование? Посетите мой онлайн-курс «Тестирование Node.js и JavaScript от А до Я»

Do: Обычно мы выбираем несколько входных образцов для каждого теста. Даже когда формат ввода похож на реальные данные (см. Маркер «Don’t foo»), мы охватываем только несколько входных комбинаций (method (», true, 1), method («string», false », 0 )) , однако в производственной среде API, который вызывается с 5 параметрами, может быть вызван с тысячами различных перестановок, одна из которых может привести к остановке нашего процесса (см. Fuzz Testing).Что, если бы вы могли написать один тест, который автоматически отправляет 1000 перестановок различных входных данных и улавливает, для каких входных данных наш код не может вернуть правильный ответ? Тестирование на основе свойств — это метод, который делает именно это: отправляя все возможные комбинации входных данных вашему тестируемому модулю, он увеличивает интуитивность обнаружения ошибки. Например, для метода — addNewProduct (id, name, isDiscount) — поддерживающие библиотеки будут вызывать этот метод с множеством комбинаций (число, строка, логическое значение), например (1, «iPhone», false), (2, «Galaxy» «, правда).Вы можете запускать тестирование на основе свойств с помощью вашего любимого средства выполнения тестов (Mocha, Jest и т. Д.), Используя такие библиотеки, как js-verify или testcheck (гораздо лучшая документация). Обновление: Николас Дубьен предлагает в комментариях ниже выполнить быструю проверку, которая, кажется, предлагает некоторые дополнительные функции, а также активно поддерживается

В противном случае: Бессознательно вы выбираете тестовые входы, которые охватывают только те пути кода, которые работают хорошо. К сожалению, это снижает эффективность тестирования как средства выявления ошибок.

☺ Делаем правильно Пример: Тестирование множества входных перестановок с помощью «mocha-testcheck»

Do: К настоящему времени, вероятно, очевидно, что я ‘ m выступает за чрезвычайно простые тесты: команда не может позволить себе еще один программный проект, требующий умственных усилий для понимания кода.Майкл Линк объясняет это в своем замечательном посте:

Хороший производственный код хорошо продуман; хороший тестовый код очевиден… Когда вы пишете тест, подумайте о следующем разработчике, который увидит паузу в тестировании. Они не хотят читать весь ваш набор тестов, и, конечно же, не хотят читать все дерево наследования утилит тестирования.

Позвольте читателю получить всю историю, не выходя из теста, минимизируйте утилиты, перехватчики или любое внешнее воздействие на тестовый пример.Слишком много повторов и копировальных вставок? Хорошо, тест может пройти с одним внешним помощником и остаться очевидным. Но когда он вырастает до трех или четырех помощников и перехватчиков, это означает, что сложная структура медленно формируется

В противном случае: Внезапно вы обнаружите, что 4 помощника на набор тестов, 2 из них наследуются от базового утилит, много крючков настройки и отрывания? поздравляю, вы только что выиграли еще один сложный проект, который нужно поддерживать. Возможно, вы скоро будете писать тесты для вашего набора тестов.

😕 Пример анти-шаблона: Необычная и непрямая структура тестирования.Вы понимаете тестовый пример без перехода к внешним зависимостям?

☺ Делаем правильно Пример: Тест, который вы можете понять, не переходя по разным файлам

Do Выполните: Следуя золотому правилу (маркер 0), каждый тест должен добавлять и действовать на своем собственном наборе строк БД чтобы предотвратить сцепление и легко рассуждать о тестовом потоке. На самом деле, это часто нарушается тестировщиками, которые заполняют базу данных данными перед запуском тестов (также известных как «приспособление для тестирования») ради повышения производительности.Хотя производительность действительно вызывает беспокойство — ее можно уменьшить (см. Раздел «Тестирование компонентов»), однако сложность тестирования — это очень болезненное горе, которое в большинстве случаев должно определять другие соображения. Фактически, заставьте каждый тестовый пример явно добавлять нужные ему записи БД и действовать только с этими записями. Если производительность становится критической проблемой — сбалансированный компромисс может быть заключен в форме заполнения единственного набора тестов, которые не изменяют данные (например, запросы)

В противном случае: Несколько тестов не пройдут, развертывание прерывается, наша команда собираюсь потратить драгоценное время, у нас есть ошибка? давайте исследуем, о нет — похоже, что два теста мутировали одни и те же начальные данные

😕 Пример антипаттерна: тесты не являются независимыми и полагаются на какой-то глобальный перехватчик для подачи глобальных данных БД

☺Пример правильного выполнения: Мы можем оставаться в рамках теста, каждый тест действует на своем собственном наборе данных

Do: При попытке утверждать, что какой-то ввод вызывает ошибку, может показаться правильным использовать try-catch-finally и утверждать, что была введена оговорка о улове.Результатом является неудобный и подробный тестовый пример (пример ниже), который скрывает простое намерение теста и ожидаемые результаты

Более элегантной альтернативой является использование однострочного специального утверждения Chai: expect (method) .to.throw ( или в Jest: expect (method) .toThrow ()). Абсолютно обязательно также убедиться, что исключение содержит свойство, указывающее тип ошибки, в противном случае, учитывая общую ошибку, приложение не сможет многое сделать, а не покажет пользователю разочаровывающее сообщение

В противном случае: Из отчетов об испытаниях будет сложно сделать вывод (например,грамм. CI сообщает), что пошло не так

😕 Пример анти-шаблона: Длинный тестовый пример, который пытается подтвердить существование ошибки с помощью try-catch

☺Пример: Человекочитаемое ожидание, которое может быть легко понять, может быть, даже QA или технический PM

Do: Различные тесты должны выполняться в разных сценариях: быстрый дым, без ввода-вывода, тесты должны запускаться, когда разработчик сохраняет или фиксирует файл, полный сквозной тесты обычно запускаются при отправке нового запроса на перенос и т. д.Этого можно достичь, пометив тесты такими ключевыми словами, как #cold #api #sanity, чтобы вы могли использовать grep с помощью своих средств тестирования и вызывать желаемое подмножество. Например, вот как вы вызываете только группу тестов работоспособности с помощью Mocha: mocha — grep ‘sanity’

В противном случае: Запуск всех тестов, включая тесты, которые выполняют десятки запросов к БД, каждый раз, когда разработчик выполняет небольшое изменение может быть очень медленным и удерживает разработчиков от запуска тестов

☺️ Doing It Right Example: Пометка тестов как ‘# cold-test’ позволяет исполнителю тестов выполнять только быстрые тесты (Cold === быстрые тесты, которые не выполняет операций ввода-вывода и может выполняться часто, даже когда разработчик набирает текст)

Do: Этот пост посвящен советам по тестированию, которые связаны или, по крайней мере, могут быть проиллюстрированы с помощью Node JS. Тем не менее, этот пункт объединяет несколько хорошо известных не-узловых связанных советов

Изучите и применяйте принципы TDD — они чрезвычайно ценны для многих, но не пугайтесь если они не подходят вашему стилю, вы не единственный. Рассмотрите возможность написания тестов перед кодом в стиле красно-зеленого рефакторинга, убедитесь, что каждый тест проверяет ровно одну вещь, когда вы обнаружите ошибку — перед исправлением напишите тест, который обнаружит эту ошибку в будущем, пусть каждый тест завершится неудачей по крайней мере один раз перед тем, как стать зеленым, избегайте любой зависимости от среды (пути, ОС и т. д.)

В противном случае: Вы пропустите жемчужины мудрости, которые собирались десятилетиями

10+ инструментов для имитации HTTP-запросов

Мокинг HTTP запросы — важная часть любого тестового полка.Способность тестировать широкий спектр возможных ситуаций, реалий и вариантов использования чрезвычайно важна, и это дает прекрасную возможность действительно защитить ваш API в будущем. Какой инструмент вы используете для реализации этого, имеет значение — ваш инструмент должен иметь возможность имитировать общие взаимодействия API и потоки HTTP-запросов, и, что наиболее важно, он должен соответствовать вашей данной базе кода и ситуации.

Сегодня мы рассмотрим инструменты 10 для имитации HTTP-запросов . Каждый из этих инструментов предлагает что-то немного отличающееся от других и представляет множество интересных вариантов сборки и реализаций.

Nock — это библиотека HTTPS, предназначенная для репликации и имитации серверов и ожиданий в Node.js. Функционально Нок делает это, переопределяя функции http.request и http.ClientRequest, перехватывая запросы и отвечая определенным имитируемым ответом с помощью перехватчиков.

Перехватчики адресуются в том порядке, в котором они появляются в списке, что означает, что вы можете создать несколько перехватчиков, которые будут давать разные ответы на два или более вызовов. Это особенно полезно, если вы тестируете фиктивные сбои или маршрутизацию, поскольку вы можете относительно легко имитировать сложные функции сервера.

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

MockServer (и его аналог сервис MockServer Proxy) — это многогранный инструмент, который поставляется в различных сборках. Он доступен как веб-сервер Netty, контейнер Docker, плагин Maven, плагин npm и плагин Grunt.Существует множество отличных вариантов, которые можно использовать в самых разных средах. Это уже делает его довольно привлекательным инструментом, учитывая, что вы можете подключить его практически ко всему, что вы используете, но его широкий набор функций является основным убедительным аргументом.

MockServer отвечает на запросы на основе ряда настроенных ожиданий, включая поддержку фиктивных ответов, пересылку запроса, создание обратного вызова, недопустимый ответ / закрытие соединения, тестовое утверждение и получение журнала.По этой причине MockServer хорошо определен и настраивается, что делает его отличным вариантом для большинства случаев использования.

Beeceptor — отличный инструмент в значительной степени потому, что он не требует абсолютно никакого кода для его использования. Beeceptor — это бесплатный онлайн-инструмент для имитации взаимодействия REST API с использованием любого HTTP-запроса. Вы можете настроить свои ответы так, чтобы имитировать практически любую реакцию или ситуацию отказа. Beeceptor также предлагает отличную функциональность для имитации задержки в нисходящих API — вы можете моделировать как задержку передачи, так и тайм-ауты, что является отличным вариантом использования для многих API и часто упускается во время тестирования.

Beeceptor также имеет отличную поддержку для A / B-тестирования. Это еще один вариант использования, который часто упускают из виду другие варианты имитации, или, если он поддерживается, он требует повторного развертывания или специальных конфигураций тестирования. Beeceptor поддерживает A / B-тестирование без необходимости повторного развертывания или использования нескольких тестовых сред, что может показаться небольшим преимуществом, но на самом деле приводит к гораздо более чистому, компактному и эффективному устройству тестирования.

Mockoon отличается от других решений в этом списке тем, что не является ни веб-решением, ни решением для кода.Mockoon — это загружаемая программа, которая имитирует неограниченное количество сред и маршрутов — Mockoon подчеркивает, что они могут работать параллельно, а его мощная система импорта / экспорта гарантирует, что корпоративные, многопутевые, многопользовательские ситуации могут быть адекватно поддерживается.

Помимо нового метода развертывания, Mockoon предлагает широкий спектр поддержки общих серверных переменных. Самозаверяющие сертификаты, ответы, запускаемые правилами, моделирование задержки и другие функции для репликации общих условий сервера, позволяя при этом достаточно гибкие параметры конфигурации, чтобы имитировать практически любую систему.Обращает на себя внимание тот факт, что вам не нужно регистрироваться или развертывать в облаке — все делается локально.

Mocky — невероятно простая и сверхлегкая реализация тестирования. Mocky — это полностью веб-приложение, а это означает, что все создается и управляется удаленно. Это означает, что Mocky предоставляет вам значительно меньше контроля по сравнению с решениями, которые больше ориентированы на локальные системы, но это также означает, что приложение проще и чище.

Mocky имеет отличную поддержку множества общих функций, но, поскольку это веб-приложение, вы должны добавить эту функциональность в форме URL-адреса.Например, добавление ? Callback = myfunction включает jsonp; добавление ? mocky-delay = 100ms позволяет добавлять задержки. Подобная функциональность по-прежнему имеет большую ценность, но указывает на относительную простоту приложения — если желательно превышение детального контроля, Mocky может быть не первым вариантом. Однако для простых взаимодействий Mocky — отличный выбор.

Mockable был разработан с нуля, чтобы быть простым и легким в использовании, и это показывает — все, что Mockable делает и представляет, гладко и интуитивно понятно.Из-за такого стремления к проектированию невероятно быстро превратиться из ничего в имитацию сервера.

Следует отметить, что Mockable, похоже, купил его, чтобы предложить решение в первую очередь корпоративным пользователям. Возможность организовать макеты в «Домене», коллекции, в которой несколько пользователей могут взаимодействовать с поддоменами и макетами, а также с помощью командных инструментов, построенных на системе Доменов, предполагает, что это в основном нацелено на этот конкретный сегмент.

Тем не менее, это по-прежнему очень хороший выбор, предлагающий широкий спектр функций и расширений для того, что он делает.

Stoplight — это быстрое создание макетов серверов и визуализация API-интерфейсов, которые с ними взаимодействуют. Благодаря множеству инструментов Stoplight предлагает отличную виртуализацию, автоматическую проверку на соответствие документации OpenAPI и высокую поддержку настраиваемого и динамического создания контента.

Stoplight также построен на Prism, предложении имитатора HTTP с открытым исходным кодом. Открытый исходный код является огромным преимуществом, и тот факт, что он также поддерживает Swagger, определенно является еще одним преимуществом.

Следует также отметить, что стоп-сигнал на самом деле представляет собой серию предложений, а не единственную опцию. Для обычных пользователей это включает в себя Stoplight Studio (фактическая реализация имитации) и Stoplight Docs, мощный механизм документации, который генерирует документацию из OpenAPI v2 / v3. Для корпоративных пользователей Stoplight Hubs — это развертываемый центр документации для нестандартной фирменной документации, а Stoplight Enterprise — это его стандартные предложения, расширенные для внедрения на предприятии.

Мок-серверы в Postman напрямую привязаны к приложению Postman, и по этой причине являются предложением для очень конкретного случая использования. Postman — отличное решение для тестирования, и их система фиксации одинаково хороша, но тот факт, что он привязан как к учетной записи Postman, так и к определенной коллекции, означает, что использование только системы Mocking означает, что вы покупаете неполный опыт тестирования. Вы можете создать макет сервера без существующей коллекции, но в этом случае это похоже на покупку всего швейного набора для одной иглы.

Это, конечно, не может помешать сделке — Postman — отличная система тестирования, которая относительно часто используется многими разработчиками API. Тем не менее, тот факт, что имитирующая система является лишь одним аспектом гораздо более крупного испытательного устройства, может отпугнуть некоторых пользователей. Кроме того, он не является полностью бесплатным: Postman допускает ограниченное количество бесплатных имитационных звонков, но пользователи, занятые тяжелой разработкой, могут быстро исчерпать это ограниченное количество.

Wiremock позиционирует себя как «симулятор для API на основе HTTP» — по сути, это инструмент виртуализации для имитации, но продукт, похоже, соответствует идее целостного моделирования.Mocklab делает еще один шаг вперед, предлагая имитацию через веб-интерфейс. Основным преимуществом Wiremock является гибкость развертывания — он может похвастаться развертыванием с помощью множества реализаций и «быстрой заменой […] одной строкой кода», что делает его довольно гибким для ряда решений.

Пожалуй, двумя самыми сильными преимуществами Wiremock являются сопоставление запросов и захват трафика. Сопоставление может выполняться по URL-адресам, методам, заголовкам, файлам cookie и телам с использованием JSON и XML, а также множества других параметров.Это, в сочетании с относительно надежными функциями записи и воспроизведения, которые позволяют захватывать и анализировать трафик, означает, что имитационное тестирование может выполняться довольно надежно.

Mockserver — это библиотека, которая использует фиктивные файлы для предоставления реалистичных фиктивных ответов. Он делает это путем создания локальных фиктивных файлов, которые обслуживают контент, как если бы они были частью реального API, локализованного на порту 9001. Благодаря относительно чистой и быстрой реализации Mockserver может похвастаться тем, что фиктивный API-интерфейс может быть создан «за секунды» — Более того, поскольку такая система сверхлегкая, это также означает, что она легко адаптируется к широкому спектру опций.

По этой причине Mockserver — отличный вариант, если требуется быстрое и относительное тестирование. Mockserver является подробным, поддерживает настраиваемые заголовки, имеет встроенную схему моделирования задержки ответа и предлагает широкий спектр дополнительных опций для имитации стандартных сред тестирования.

Как и в любом другом подобном списке, ваш выбор действительно продиктован вашей текущей ситуацией. Любой вариант, описанный здесь, будет выполнять работу по имитации HTTP-запросов с относительной легкостью и эффективностью, хотя режим выполнения и результат указанного выполнения могут меняться от реализации к реализации.Тем не менее, все эти варианты прекрасны в своем конкретном случае использования и могут быть использованы для обеспечения быстрой, чистой и интуитивно понятной среды для тестирования и итеративной разработки.

Что вы думаете о представленных здесь вариантах? Мы упускаем из виду какие-либо основные варианты насмешек? Дайте нам знать в комментариях ниже.

Пояснение — Urbit

Чтобы Нок имел смысл, давайте поработаем со спецификацией построчно.
Сначала модель данных:

Существительные

  Атом - это любое натуральное число.Существительное - это атом или клетка.
Клетка - это любая упорядоченная пара существительных.
  

Существительные — самая тупая модель данных. Существительные делают JSON похожим на
XML и XML выглядят как ASN.1. Это также может напомнить вам о Лиспе
S-выражения — вы можете думать о существительных как о S-выражениях без
С. «

»

Если быть точным, существительное — это S-выражение, за исключением классического
S-выражения имеют несколько типов атомов («S» означает «символ»).
Поскольку Nock предназначен для использования с системой типов более высокого уровня
(например, Hoon), ему не нужны низкоуровневые типы.Атом — это
просто целое число без знака любого размера.

Например, строки (или даже целые
текстовые файлы) как атомы, сначала располагая их LSB — так что «foo» становится
0x6f6f66 . Откуда нам знать, что напечатать это как «foo», а не как 0x6f6f66 ?
Нам нужна внешняя информация — например, тип Hoon. По аналогии,
другие распространенные атомарные типы — целые числа со знаком, с плавающей запятой и т. д.

  • все просто сопоставить с атомами.

Также важно отметить, что, в отличие от Lisp, Nock не может создавать
циклические структуры данных.Это нормально и обычно для существительных в
Система времени выполнения Nock должна иметь ациклическую структуру — общие поддеревья.
Но нет вычислений Nock, которые могли бы указать дочернему элементу на
его родитель. Одно из следствий: у Нока нет сборщика мусора.
(Также не может быть обнаружена структура dag, как в Lisp eq .)

Также нет единого синтаксиса для существительных. Если у вас есть существительные
есть Нок; если у вас есть Nock, у вас есть Hoon; если у тебя есть Хун, ты
можете написать любой парсер, который вам нравится.

Скидки

Важно понимать, что псевдокод спецификации Nock
это просто псевдокод.Это немного похоже на Хуна. Это не
Хун — это просто псевдокод. Другими словами, просто английский.
В основе каждой формальной системы лежит система аксиом, которая
можно писать только на английском. (Почему псевдокод, а не Хун?
Hoon определяется в Nock, это может создать ложное впечатление.
несуществующей точности.)

Логика этого псевдокода — сокращение сопоставления с образцом,
соответствие сверху вниз. Чтобы вычислить Nock, несколько раз уменьшайте
с первой совпадающей строкой.Давайте прямо сейчас!

Ноковые принципы

  нок (а) * а
  

Nock — это чистая (без сохранения состояния) функция от существительного до существительного. В нашем
псевдокодом (и только в нашем псевдокоде) мы выражаем это с помощью
префиксный оператор * .

Эта функция определена для каждого существительного, но для многих существительных она
ничего полезного не делает. Например, если a — это атом, * a
сокращается до … * . Теоретически это означает, что Нок крутится
навсегда в бесконечном цикле.Другими словами, Nock не производит
результат — и на практике ваш переводчик остановится.

(Другой способ убедиться в этом состоит в том, что у Nock есть семантика «только сбой».
Механизма исключения нет. Единственный способ поймать Нока
ошибок заключается в моделировании Нока в виртуальном Ноке более высокого уровня —
что, по сути, мы делаем постоянно. Симулятор (или практический
низкоуровневый переводчик) может внеполосно сообщать, что Нок
не прекращать. Он не может распознать все бесконечные петли
Конечно, но может улавливать очевидные — вроде * 42 .)

Обычно a in nock (a) — это ячейка [s f] , или, как мы говорим,

  [подлежащая формула]
  

Интуитивно понятно, что формула — это ваша функция, а предмет — это
свой аргумент. Мы называем их иначе, потому что Hoon,
или любой другой язык высокого уровня, построенный на Nock, построит свой
собственное соглашение о вызове функций, которое не отображает напрямую
на * [подлежащая формула] .

Синтаксис существительного

  [a b c] [a [b c]]
  

Т.е., скобки (в нашем псевдокоде, как в Hoon) связывают
верно.Для тех, у кого есть опыт работы с Lisp, важно отметить
что Нок и Хун гораздо чаще используют кортежи или «неправильные списки»
сильнее, чем Лисп. Терминатор списка, обычно 0, никогда не бывает
автомат. Итак, список Lisp

  (а б в)
  

становится существительным Nock

  [a b c 0]
  

, что эквивалентно

  [a [b [c 0]]]
  

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

Тривиальные операторы

 ? [A b] 0
? a 1
+ [а б] + [а б]
+ а 1 + а
= [а а] 0
= [а б] 1
  

Здесь мы определяем дополнительные операторы псевдокода, которые мы будем использовать в
снижение далее вниз.Пока у нас есть четыре встроенных функции:
* имеется ввиду сам Нок, ? проверка того, является ли существительное ячейкой или
атом, + приращение атома, и = проверка на равенство.
Опять же, здесь нет ракетостроения.

Следует отметить, что в Nock and Hoon 0 (произносится «да»)
истина, а 1 («нет») — ложь. Почему? Как и в Unix, используя ноль для
успех плавно обобщается на множественные коды ошибок. И это
странно для успеха не равняться истине.Или, по крайней мере, это
наше официальное оправдание.

Древовидная адресация

  / [1 a] a
/ [2 а б] а
/ [3 а б] б
/ [(a + a) b] / [2 / [a b]]
/ [(a + a + 1) b] / [3 / [a b]]
  

Чуть интереснее наша древовидная нумерация. Каждое существительное
конечно дерево. Оператор / — произносится как «слот» — накладывает
адресное пространство на этом дереве, отображая каждый ненулевой атом в
положение дерева.

1 — это корень. Голова каждого узла n 2n ; хвост
2н + 1 .Таким образом, простое дерево:

  1
  2 3
4 5 6 7
         14 15
  

Если значением каждого листа является его адрес дерева, это дерево

  [[4 5] [6 14 15]]
  

и, для некоторых примеров адресации:

  / [1 [[4 5] [6 14 15]]]
  

— это [[4 5] [6 14 15]]

  / [2 [[4 5] [6 14 15]]]
  

— это [4 5]

  / [3 [[4 5] [6 14 15]]]
  

— это [6 14 15] и

.

  / [7 [[4 5] [6 14 15]]]
  

— это [14 15]

Надеюсь, это не так уж и сложно.

Редактирование существительного,

#

  # [1 a b] a
# [(a + a) b c] # [a [b / [(a + a + 1) c]] c]
# [(a + a + 1) b c] # [a [/ [(a + a) c] b] c]
  

Оператор # заменяет часть существительного на другое существительное. # [x y z] заменяет адрес x из z на существительное y .

Возьмите какое-нибудь существительное, скажем, [22 33 44 55] . Давайте заменим его часть другим существительным, [123 456] .Мы можем заменить существительное полностью следующим образом:

  # [1 [123 456] [22 33 44 55]]
  

это

  [123 456]
  

Если мы хотим заменить значение только по адресу 2 :

  # [2 [123 456] [22 33 44 55]]
  

это

  [[123 456] 33 44 55]
  

И мы можем заменить адрес 3 :

  # [3 [123 456] [22 33 44 55]]
  

это

  [22 123 456]
  

Инструкции

Эти правила определяют сам Nock, то есть оператор * .

0 , паз

  * [a 0 b] / [b a]
  

0 — это инструкция Нока по древовидной адресации. Давай попробуем
из командной строки Arvo.

Обратите внимание, что здесь мы используем синтаксис Hoon. Поскольку мы не используем Nock
из Hoon так часто (это как встраивание сборки в
C), мы оставили его немного громоздким. В Хун вместо
пишем * [a 0 b] , пишем

 . * (A [0 b])
  

Итак, чтобы повторно использовать наш пример слота, давайте попробуем интерпретатор:

  ~ zod: dojo>.* ([[4 5] [6 14 15]] [0 7])
  

производит [14 15] .

1 , постоянная

  * [a 1 b] b
  

1 — постоянная инструкция. Он приводит аргументы без
ссылка на тему. Итак

  ~ zod: dojo>. * (42 [1 153 218])
  

дает [153 218] .

2 , оценить

2 — это инструкция Nock:

  * [a 2 b c] * [* [a b] * [a c]]
  

Если вы можете вычислить предмет и
формулу, вы можете вычислить их в интерпретаторе.В большинстве
фундаментальные языки, такие как Lisp, eval — диковинка. Но
У Нока нет apply — поэтому вся наша работа выполняется с 2 .

Давайте превратим предыдущий пример в тупое использование 2 ,
с постоянной темой и формулой:

  ~ zod: dojo>. * (77 [2 [1 42] [1 1 153 218]])
  

Это дает то же значение [153 218]

3 , 4 и 5 , аксиоматические функции

  * [a 3 b]? * [A b]
* [a 4 b] + * [a b]
* [a 5 b c] = [* [a b] * [a c]]
  

Это аксиоматические функции:

Например, если x — это формула, по которой вычисляется некоторый продукт,
[4 x] вычисляет это произведение плюс один.Отсюда:

  ~ zod: dojo>. * (57 [0 1])
57
~ zod: dojo>. * (57 [4 0 1])
58
  

Аналогично

  ~ zod: dojo>. * ([132 19] [0 3])
19
~ zod: dojo>. * ([132 19] [4 0 3])
20
  

Распределение

  * [a [b c] d] [* [a b c] * [a d]]
  

Поскольку Nock атома просто рушится, практическая область
Нок-функция — это всегда ячейка. Условно глава этого
ячейка — это тема, хвост — формула, а результат
Nocking это «продукт».»По сути, это ваша
данные и формула — это ваш код.

Мы могли бы написать эту строку менее формально:

  * [субъект [формула-x формула-y]]
=> [* [подлежащая формула-x] * [подлежащая формула-y]]
  

Другими словами, если у вас есть две формулы Нока x и y , a
формула, которая вычисляет их пару, равна [x y] . Мы можем
признать это, потому что никакой атом не является действительной формулой, и
каждая формула, которую не использует в распределении, имеет атомарную головку.

Если вы знакомы с Lisp, вы можете рассматривать эту функцию как своего рода
«неявные минусы». Где в Лиспе вы должны написать (cons x y) ,
в ноке вы пишете [x y] .

Например,

  ~ zod: dojo>. * (42 [4 0 1])
  

, где 42 — предмет (данные), а [4 0 1] — формула
(код), оказывается, оценивается как 43 . Тогда как

  ~ zod: dojo>. * (42 [3 0 1])
  

— это 1 .Итак, если мы оценим

  ~ zod: dojo>. * (42 [[4 0 1] [3 0 1]])
  

получаем

  [43 1]
  

За исключением значений по умолчанию для сбоя, мы на самом деле
завершил все существенных аспектов Нока. Инструкции вверх
через 5 обеспечивают все необходимые вычислительные функции.
Нок, хотя и очень простой, на самом деле намного сложнее, чем он.
формально должно быть.

Операторы с 6 по 11 — сахар. Они существуют, потому что Нок
не игрушка, а практический переводчик.Посмотрим их все
вместе:

Сахар

  * [a 6 b c d] * [a * [[c d] 0 * [[2 3] 0 * [a 4 4 b]]]]
* [a 7 b c] * [* [a b] c]
* [a 8 b c] * [[* [a b] a] c]
* [a 9 b c] * [* [a c] 2 [0 1] 0 b]
* [a 10 [b c] d] # [b * [a c] * [a d]]

* [a 11 [b c] d] * [[* [a c] * [a d]] 0 3]
* [a 11 b c] * [a c]
  

Давайте попробуем разобраться, что они делают, сначала самое простое:

11 , подсказка

  * [a 11 b c] * [a c]
  

Если x — атом, а y — формула, формула [11 x y]
похоже на… л . Например:

 . * ([132 19] [11 37 [4 0 3]])
  

Зачем нам это нужно? 11 на самом деле является подсказкой.
37 в этом примере — это отброшенная информация — это не
формально используется в вычислениях. Это может помочь переводчику
Однако вычислить выражение более эффективно.

Каждый Nock дает один и тот же результат, но не все одновременно
скорость. Какие подсказки поддерживаются? Что они делают? Подсказки
соглашения более высокого уровня, которые не должны и не должны появляться в
спецификация Nock.Некоторые определены в Hoon. Действительно, наивный Нок
интерпретатор, не оптимизированный для Hoon, будет плохо запускать Hoon.
Однако когда он получит товар, он будет правильным.

Есть еще одна инструкция 11 правило:

  * [a 11 [b c] d] * [[* [a c] * [a d]] 0 3]
  

Эта сложная подсказка
отбрасывает произвольный b , но вычисляет формулу c
против предмета и … выбрасывает товар. Эта формула
просто эквивалентно d .Конечно, на практике продукт
из c будет использоваться в грязных и полезных целях. Это могло даже
заводится как побочный эффект.

(Зачем нам вообще нужно вычислять c ? Потому что c может
крушение. Правильный Нок не может просто игнорировать его и лечить оба
варианты 11 как эквивалент.)

7 , составить

  * [a 7 b c] * [* [a b] c]
  

Предположим, у нас есть две формулы: b и c .Какая формула
[7 b c] ? Этот пример покажет вам:

  ~ zod: dojo>. * (42 [7 [4 0 1] [4 0 1]])
44 год
  

Старый добрый состав, по формулам Нока. Легко увидеть, как
это вариант Nock 2 . Данные для оценки — это просто b ,
и формула c цитируется.

8 , продлить

  * [a 8 b c] * [[* [a b] a] c]
  

8 — это 7 , за исключением того, что предмет c — это не просто
продукт b , но заказанная пара продукта b и
исходный предмет.Отсюда:

 . * (42 [8 [4 0 1] [0 1]])
[43 42]
  
  ~ zod: dojo>. * (42 [8 [4 0 1] [4 0 3]])
43 год
  

Зачем нам это нужно? Представьте себе язык более высокого уровня
в котором программист объявляет переменную. Этот язык
вероятно сгенерирует 8 , потому что переменная вычисляется
против данного предмета и используется в расчетах, которые
зависит как от исходного объекта, так и от новой переменной.

9 , вызвать

9 является условным обозначением:

  * [a 9 b c] * [* [a c] 2 [0 1] 0 b]
  

С c мы производим существительное, которое содержит как код, так и данные — a
ядро ​​.Мы используем это ядро ​​в качестве предмета и оцениваем
формула в слоте b .

6 , если-то-еще

Это выглядит намного страшнее, чем есть на самом деле:

  * [a 6 b c d] * [a * [[c d] 0 * [[2 3] 0 * [a 4 4 b]]]]
  

Если b оценивается как 0 , мы производим c ; если b оценивается как 1 ,
производим d ; в противном случае мы рухнем.

Например:

  ~ zod: dojo>.* (42 [6 [1 0] [4 0 1] [1 233]])
43 год
~ zod: dojo>. * (42 [6 [1 1] [4 0 1] [1 233]])
233
  

В реальной жизни, конечно, разработчик Nock знает, что 6
«если» и реализует это как таковое. Практического смысла в
уменьшение с помощью этого или любого другого макроса. Мы могли бы иметь
определил «если» как встроенную функцию, как приращение, за исключением того, что
мы можем написать «если» как макрос. Если обалденный макрос.

Фактически мы можем упростить семантику 6 за счет
немного сломать систему, создав макрос, который работает как
«если», только если b является правильным логическим значением и дает 0 или 1 .Возможно, у нас есть система типов более высокого уровня, которая это проверяет.

Это более простое «если» будет:

  * [a 6 b c d] * [a [2 [0 1] [2 [1 c d] [[1 0] [4 4 b]]]]]]
  

Или без лишних скобок:

  * [a 6 b c d] * [a 2 [0 1] 2 [1 c d] [1 0] [4 4 b]]
  

Как это работает? Мы заменили [6 b c d] формулой
[2 [0 1] [2 [1 c d] [[1 0] [4 4 b]]]]] . Мы видим два использования 2 ,
наша инструкция по оценке — внешняя и внутренняя.

Позвонить на внутренний и . Итак, у нас есть [2 [0 1] i] . Что значит
что для расчета нашего продукта мы используем [0 1] — то есть
исходный предмет — как предмет; и продукт и как
формула.

Ладно, круто. Итак, i — это [2 [1 c d] [[1 0] [4 4 b]]] . Мы вычисляем
Нок с предметом [1 c d] , формула [[1 0] [4 4 b]] .

Очевидно, что [1 c d] производит только [c d] — то есть заказанный
пара формул «then» и «else». [[1 0] [4 4 b]] — это
линия 19 клетки — ее голова [1 0] , производит только 0 , ее хвост
[4 4 b] , производит … что? Хорошо, если [4 b] — это b плюс 1 ,
[4 4 b] — это b плюс 2 .

Мы предполагаем, что b производит либо 0 , либо 1 . Так [4 4 b]
дает 2 или 3 . [[1 0] [4 4 b]] — это либо [0 2] , либо
[0 3] .Применительно к предмету [c d] это дает нам либо
c или d — продукт нашей внутренней оценки i . Это
применяется к исходному объекту, и в результате получается «если».

Но нам нужна полная мощность фанка, потому что если b производит,
скажем, 7 , это приведет к разного рода странностям. Нам бы очень хотелось
6 , чтобы просто аварийно завершить работу, если тестовый продукт не является логическим. Как может
мы добьемся этого? Это отличный способ доказать
сами понимаете, Нок: разберитесь, что на самом деле 6
делает.Или вы можете просто согласиться с тем, что 6 — это «если», и двигаться дальше.

(Стоит отметить, что на практике Nock, генерируемый компилятором, мы
никогда не делайте ничего более крутого, чем эти внутренние макросы 6 . Есть
нет причин, по которым мы не можем создавать формулы во время выполнения, но у нас нет
причина, а мы нет — кроме случаев, когда на самом деле метапрограммирование.
Как и в большинстве языков, обычно код — это код, а данные — это данные.)

Следующая:

Пример

Nock Definition — Urbit

Nock — это полная по Тьюрингу функция, отображающая ячейку
[подлежащая формула] существительное произведение , где субъект — это
data, формула — это код, а product — результат.

Это все, что вам нужно знать для программирования на Hoon.
Хотя, вероятно, стоит хотя бы бегло взглянуть на определение.

(Кроме того, программист Hoon должен знать, что (а) хвостовой вызов
устранение в Nock несложно; и (б) хвостовые крики в
Хун всегда становится хвостовым криком в Ноке.)

Правила

Nock — интерпретатор комбинатора, определенный в спецификации ниже.

Этот псевдокод описывает систему правил редукции. Переменные
соответствовать любому существительному; первое правило из лучших совпадений.

Формула, которая сводится к самой себе, представляет собой бесконечный цикл, который мы определяем как
авария («дно» в формальной логике). Настоящий переводчик
может обнаружить этот сбой и вместо этого выдать внеполосное значение.

  Нок 4K

Существительное - это атом или клетка. Атом - это натуральное число. Клетка - это упорядоченная пара существительных.

Уменьшить по первому совпадающему образцу; переменные соответствуют любому существительному.

нок (а) * а
[a b c] [a [b c]]

? [a b] 0
? a 1
+ [а б] + [а б]
+ а 1 + а
= [а а] 0
= [а б] 1

/ [1 а] а
/ [2 а б] а
/ [3 а б] б
/ [(a + a) b] / [2 / [a b]]
/ [(a + a + 1) b] / [3 / [a b]]
/ а / а

# [1 a b] a
# [(a + a) b c] # [a [b / [(a + a + 1) c]] c]
# [(a + a + 1) b c] # [a [/ [(a + a) c] b] c]
#a #a

* [a [b c] d] [* [a b c] * [a d]]

* [a 0 b] / [b a]
* [a 1 b] b
* [a 2 b c] * [* [a b] * [a c]]
* [a 3 b]? * [a b]
* [a 4 b] + * [a b]
* [a 5 b c] = [* [a b] * [a c]]

* [a 6 b c d] * [a * [[c d] 0 * [[2 3] 0 * [a 4 4 b]]]]
* [a 7 b c] * [* [a b] c]
* [a 8 b c] * [[* [a b] a] c]
* [a 9 b c] * [* [a c] 2 [0 1] 0 b]
* [a 10 [b c] d] # [b * [a c] * [a d]]

* [a 11 [b c] d] * [[* [a c] * [a d]] 0 3]
* [a 11 b c] * [a c]

* а * а
  

Операторы

Нотация псевдокода определяет шесть префиксных операторов: ? , + ,
= , /, # и * .

? [X] уменьшается до 0 , если x — ячейка, 1 — если атом.

+ [x] сводится к атому x плюс 1 .

= [x y] сокращается до 0 , если x и y — одно и то же существительное, 1
иначе.

/ ( слот ) — оператор древовидной адресации. Корень дерева
1 ; левый дочерний элемент любого узла n — это 2n ; правильный ребенок
это 2n + 1 . / [x y] — поддерево y по адресу x .

Например, / [1 [531 25 99]] — это [531 25 99] ; / [2 [531 25 99]] 531 ; / [3 [531 25 99]] равно [25 99] ; / [6 [531 25 99]] равно 25 ; / [12 [531 25 99]] вылетает.

# ( edit ) предназначен для замены части существительного на другое существительное. # [x y z] заменяет значение в слоте x из z (т.е.е., / [x z] ) с y .

Например, # [2 11 [22 33]] — это [11 33] ; # [3 11 [22 33]] — это [22 11] ; # [4 11 [[22 33] 44]] — это [[11 33] 44] ; и # [5 11 [[22 33] 44]] — это [[22 11] 44] .

* [x y] — это функция интерпретатора Nock. x является предметом,
y — это формула.

Неправильное использование любого оператора (например, увеличение ячейки) приводит к сбою.Это указано как бесконечный цикл, но на практике вы получаете сбой.

Инструкции

Действительной формулой Нока всегда является ячейка. Если заголовок формулы —
ячейки, Нок обрабатывает и голову, и хвост как формулы, разрешает каждое
против субъекта, и производит клетки из своих продуктов. В
другими словами, программа на Лиспе (cons x y) становится Nock
формула [x y] .

Если заголовок формулы — атом, это инструкция от
0 по 11 .

Формула [0 b] сводится к существительному по адресу дерева b
в теме.

Формула [1 b] сводится к постоянному существительному b .

Формула [2 b c] обрабатывает b и c как формулы, разрешает каждую
против субъекта, затем снова вычисляет Нок с произведением
b как предмет, c как формула.

В формулах [3 b] и [4 b] , b — другое
формула, произведение которой на предмет становится исходным для
аксиоматический оператор. 3 это ? и 4 — это +

Формула [5 b c] обрабатывает b и c как формулы, которые становятся входными данными для другого аксиоматического оператора, = .

Инструкции с 6 по 11 не являются строго обязательными для полноты по Тьюрингу; удаление их
от Нока уменьшила бы компактность, но не выразительность.

[6 b c d] — это , если b , тогда c , иначе d .Каждый из б ,
c , d — формула против предмета. Помните, что 0 — это
истина и 1 ложь.

[7 b c] составляет формулы b и c .

[8 b c] производит продукт формулы c , против
субъект, голова которого является произведением формулы b с
исходный объект, и чей хвост является исходным объектом. (Считать
из 8 как «объявление переменной» или «выталкивание стека.»)

[9 b c] вычисляет произведение формулы c на текущий
предмет; из этого продукта d он извлекает формулу e в дереве
адрес b , затем вычисляет * [d e] . ( 9 предназначен для
Хун; d — стержень (объект), e указывает на руку (метод).)

В формуле [10 [b c] d] , c и d вычисляются с текущим объектом, а затем b произведения d заменяется произведением c .

[11 b c] — подсказка семантически эквивалентна формуле
с . Если b — атом, это статическая подсказка , которая просто
отброшен. Если b — это ячейка, это динамическая подсказка ; глава
b отбрасывается, а хвост b выполняется как формула
против текущей темы; продукт этого выбрасывается.

Практический интерпретатор может делать что угодно с отброшенными данными, поэтому
пока результат, который он вычисляет, соответствует семантике
Нок.Например, простейшее использование подсказок — это обычное
«отладить printf.» Переводчик ошибочно пропускает
вычисление динамических подсказок; они могут разбиться.

Реализация

Читатель может задаться вопросом, как интерпретатор, единственная арифметика которого
операция приращение может когда-либо быть практичной.

Короткий ответ: интерпретатор Нока не должен использовать
алгоритм выше. Он просто должен получить тот же результат , что и
алгоритм выше.

Алгоритм декремента атома состоит в том, чтобы считать до него,
O (n) операция.Но если интерпретатор знает, что он запускает
по формуле декремента, он может напрямую использовать ЦП для декремента.

Обнаружение любой формулы Нока, семантика которой соответствует некоторой функции,
как декремент, это сложная проблема. Но на практике есть только
один декремент, который мы запускаем — декремент в библиотеке ядра.
Объявление этой формулы (с подсказкой, инструкция 11 выше)
и признать это несложно.

Следующая:

Пояснение

Настройка Jest · Jest

Конфигурация Jest может быть определена в пакете .json вашего проекта, или через файл jest.config.js , или jest.config.ts или через --config вариант. Если вы хотите использовать свой package.json для хранения конфигурации Jest, на верхнем уровне следует использовать ключ "jest" , чтобы Jest знал, как найти ваши настройки:

Или через JavaScript:

Или через TypeScript (если установлен ts-node ):

Имейте в виду, что полученная конфигурация должна быть сериализуемой в формате JSON.

При использовании параметра --config файл JSON не должен содержать ключ «jest»:

Параметры #

Эти параметры позволяют управлять поведением Jest в файле package.json . Философия Jest заключается в том, чтобы по умолчанию работать отлично, но иногда вам просто нужно больше возможностей для настройки.

Defaults #

Вы можете получить параметры Jest по умолчанию, чтобы при необходимости расширить их:


Reference #

automock [boolean] #

По умолчанию: false

Этот параметр сообщает Jest, что все импортированные модули в ваши тесты должны быть высмеяны автоматически.Все модули, используемые в ваших тестах, будут иметь заменяющую реализацию, сохраняющую поверхность API.

Пример:

Примечание. Узловые модули автоматически имитируются, если у вас есть ручной макет (например: __mocks __ / lodash.js ). Больше информации здесь.

Примечание. Основные модули, такие как fs , по умолчанию не имитируются. Их можно явно высмеивать, например jest.mock ('fs') .

залог [номер | boolean] #

По умолчанию: 0

По умолчанию Jest запускает все тесты и по завершении выводит все ошибки в консоль.Здесь можно использовать опцию конфигурации bail, чтобы Jest перестал запускать тесты после сбоев n . Установка залога на true аналогична установке залога на 1 .

cacheDirectory [строка] #

По умолчанию: "/ tmp / "

Каталог, в котором Jest должен хранить кэшированную информацию о зависимостях.

Jest пытается один раз просканировать ваше дерево зависимостей (заранее) и кэшировать его, чтобы облегчить некоторые из разгребаний файловой системы, которые должны произойти во время выполнения тестов.Этот параметр конфигурации позволяет вам настроить, где Jest хранит данные кеша на диске.

clearMocks [boolean] #

По умолчанию: false

Автоматически очищать фиктивные вызовы и экземпляры перед каждым тестом. Эквивалентно вызову jest.clearAllMocks () перед каждым тестом. Это не удаляет какую-либо имитацию реализации, которая могла быть предоставлена.

collectCoverage [логическое] #

По умолчанию: false

Указывает, следует ли собирать информацию о покрытии при выполнении теста.Поскольку при этом все исполняемые файлы заменяются операторами сбора покрытий, это может значительно замедлить ваши тесты.

collectCoverageFrom [array] #

По умолчанию: undefined

Массив шаблонов глобусов, указывающий набор файлов, для которых должна быть собрана информация о покрытии. Если файл соответствует указанному шаблону глобуса, для него будет собрана информация о покрытии, даже если для этого файла не существует тестов и они никогда не требуются в наборе тестов.

Пример:

При этом будет собрана информация о покрытии для всех файлов внутри корневого каталога проекта , кроме тех, которые соответствуют ** / node_modules / ** или ** / vendor / ** .

Примечание. Каждый шаблон глобуса применяется в том порядке, в котором они указаны в конфигурации. (Например, ["! ** / __ tests __ / **", "** / *. Js"] не будет исключать __tests__ , потому что отрицание перезаписывается вторым шаблоном. Чтобы заставить отрицательный глобус работать в этом примере он должен стоять после ** / *.js .)

Примечание. Для этого параметра требуется, чтобы для параметра collectCoverage было установлено значение true или для вызова Jest с параметром --coverage .

Справка: Если вы видите вывод покрытия, такой как …

Скорее всего, ваши шаблоны глобуса не соответствуют никаким файлам. Обратитесь к документации по микроматчу, чтобы убедиться, что ваши шарики совместимы.

extensionDirectory [строка] #

По умолчанию: undefined

Каталог, в который Jest должен выводить файлы покрытия.

extensionPathIgnorePatterns [array ] #

По умолчанию: ["/ node_modules /"]

Массив строк шаблонов регулярного выражения, которые сопоставляются со всеми путями к файлам перед выполнением теста. Если путь к файлу соответствует любому из шаблонов, информация о покрытии будет пропущена.

Эти строки шаблона соответствуют полному пути. Используйте строковый токен , чтобы включить путь к корневому каталогу вашего проекта, чтобы предотвратить его случайное игнорирование всех ваших файлов в разных средах, которые могут иметь разные корневые каталоги.Пример: ["<корневой каталог> / build /", "<корневой каталог> / node_modules /"] .

охватПровайдер [строка] #

Указывает, какой поставщик должен использоваться для инструментария кода для покрытия. Допустимые значения: babel (по умолчанию) или v8 .

Обратите внимание, что использование v8 считается экспериментальным. При этом используется встроенное покрытие кода V8, а не покрытие, основанное на Babel. Он не так хорошо протестирован, и он также улучшился в последних нескольких выпусках Node.Использование последних версий узла (v14 на момент написания) даст лучшие результаты.

охват отчетов [массив <строка | [ строка, параметры]>] #

По умолчанию: ["json", "lcov", "text", "clover"]

Список имен репортеров, которые Jest использует при написании отчетов о покрытии. Может быть использован любой стамбульский репортер.

Примечание. Установка этого параметра заменяет значения по умолчанию. Добавьте "текст" или "текст-сводку" , чтобы увидеть сводку покрытия в выходных данных консоли.

Примечание. Вы можете передать дополнительные параметры в istanbul reporter, используя форму кортежа. Например:

Для получения дополнительной информации о форме объекта параметров вы можете обратиться к типу CoverageReporterWithOptions в определениях типов.

покрытиеThreshold [объект] #

По умолчанию: undefined

Это будет использоваться для настройки минимального порогового значения для результатов покрытия. Пороговые значения могут быть указаны как global , как глобус, а также как путь к каталогу или файлу.Если пороговые значения не достигнуты, шутка не удастся. Пороговые значения, заданные как положительное число, принимаются за минимальный требуемый процент. Пороговые значения, указанные как отрицательное число, представляют максимальное разрешенное количество непокрытых объектов.

Например, со следующей конфигурацией шутка завершится ошибкой, если охват ветвей, строк и функций менее 80% или если имеется более 10 непокрытых операторов:

Если глобусы или пути указаны вместе с global , данные о покрытии для совпадающих путей будут вычтены из общего покрытия, а пороговые значения будут применяться независимо.Пороговые значения для глобусов применяются ко всем файлам, соответствующим глобусам. Если файл, указанный в пути, не найден, возвращается ошибка.

Например, со следующей конфигурацией:

Jest завершится ошибкой, если:

  • Каталог ./src/components имеет менее 40% покрытия ветвей или операторов.
  • Один из файлов, соответствующих глобусу ./src/reducers/**/*.js , покрывает менее 90% операторов.
  • Модуль ./src/api/very-important-module.js имеет менее 100% покрытие.
  • Все оставшиеся вместе взятые файлы имеют менее 50% покрытия ( глобальный ).

dependencyExtractor [строка] #

По умолчанию: undefined

Этот параметр позволяет использовать настраиваемый экстрактор зависимостей. Это должен быть модуль узла, который экспортирует объект с функцией extract . Например:

Функция extract должна возвращать итерацию ( Array , Set и т. Д.) с зависимостями, найденными в коде.

Этот модуль также может содержать функцию getCacheKey для генерации ключа кэша, чтобы определить, изменилась ли логика, и любые связанные с ней кешированные артефакты должны быть отброшены.

displayName [строка, объект] #

по умолчанию: undefined

Позволяет печатать этикетку вместе с тестом во время его выполнения. Это становится более полезным в многопроектных репозиториях, где может быть много файлов конфигурации jest.Это наглядно показывает, к какому проекту принадлежит тест. Вот примеры действительных значений.

или

В качестве дополнительной опции может быть передан объект со свойствами name и color . Это позволяет настраивать цвет фона для displayName. displayName по умолчанию имеет белый цвет, если его значение является строкой. Jest использует мел для придания цвета. Таким образом, все допустимые варианты цветов, поддерживаемые мелом, также поддерживаются шуткой.

errorOnDeprecated [boolean] #

По умолчанию: false

Сделать вызов устаревших API-интерфейсов выдачей полезных сообщений об ошибках. Полезно для облегчения процесса обновления.

extensionsToTreatAsEsm [array ] #

По умолчанию: []

Jest будет запускать файлы .mjs и .js с ближайшим package.json в поле type установлено значение модуль как модули ECMAScript.Если у вас есть какие-либо другие файлы, которые должны работать с собственным ESM, вам необходимо указать здесь их расширение.

Примечание. Поддержка ESM в Jest все еще экспериментальная, подробности см. В документации.

extraGlobals [array ] #

По умолчанию: undefined

Тестовые файлы запускаются внутри виртуальной машины, что замедляет вызовы свойств глобального контекста (например, Math ). С помощью этой опции вы можете указать дополнительные свойства, которые будут определены внутри виртуальной машины для более быстрого поиска.

Например, если ваши тесты часто вызывают Math , вы можете пройти его, установив extraGlobals .

forceCoverageMatch [array ] #

По умолчанию: ['']

Тестовые файлы обычно игнорируются при сборе покрытия кода. С помощью этой опции вы можете перезаписать это поведение и включить игнорируемые в противном случае файлы в покрытие кода.

Например, если у вас есть тесты в исходных файлах с расширением .t.js , как показано ниже:

Вы можете собрать покрытие из этих файлов с помощью параметра forceCoverageMatch .

глобальные переменные [объект] #

По умолчанию: {}

Набор глобальных переменных, которые должны быть доступны во всех тестовых средах.

Например, следующее создаст глобальную переменную __DEV__ со значением true во всех тестовых средах:

Обратите внимание, что если вы укажете здесь значение глобальной ссылки (например, объект или массив), и некоторый код изменится это значение в процессе выполнения теста, эта мутация , а не , будет сохраняться во время тестовых прогонов для других тестовых файлов.Кроме того, объект globals должен быть json-сериализуемым, поэтому его нельзя использовать для указания глобальных функций. Для этого вы должны использовать setupFiles .

globalSetup [строка] #

По умолчанию: undefined

Этот параметр позволяет использовать настраиваемый модуль глобальной настройки, который экспортирует асинхронную функцию, которая запускается один раз перед всеми наборами тестов. Эта функция получает в качестве параметра объект Jest globalConfig .

Примечание. Модуль глобальной настройки, настроенный в проекте (с использованием многопроектного средства запуска), будет запущен только при запуске хотя бы одного теста из этого проекта.

Примечание. Любые глобальные переменные, определенные с помощью globalSetup , можно прочитать только в globalTeardown . Вы не можете получить глобальные объекты, определенные здесь, в ваших тестовых наборах.

Примечание: в то время как преобразование кода применяется к связанному установочному файлу, Jest будет , а не преобразовать любой код в node_modules . Это связано с необходимостью загрузки фактических преобразователей (например, babel или машинописного текста ) для выполнения преобразования.

Пример:

globalTeardown [строка] #

По умолчанию: undefined

Этот параметр позволяет использовать настраиваемый модуль глобального разрыва, который экспортирует асинхронную функцию, которая запускается один раз после всех наборов тестов. Эта функция получает в качестве параметра объект Jest globalConfig .

Примечание. Глобальный модуль разрыва, настроенный в проекте (с использованием многопроектного средства выполнения), будет запущен только в том случае, если вы запустите хотя бы один тест из этого проекта.

Примечание. То же предостережение относительно преобразования node_modules , что и для globalSetup , применяется к globalTeardown .

haste [объект] #

По умолчанию: undefined

Это будет использоваться для настройки поведения jest-haste-map , внутренней системы поиска файлов / кеширования Jest. Поддерживаются следующие параметры:

injectGlobals [boolean] #

По умолчанию: true

Вставить глобальные объекты Jest ( ожидают , test , описывают , перед каждым и т. Д.) в глобальную среду. Если вы установите это значение false , вы должны импортировать из @ jest / globals , например

Примечание. Эта опция поддерживается только при использовании по умолчанию jest-circus . исполнитель тестов

maxConcurrency [число] #

По умолчанию: 5

Число, ограничивающее количество тестов, которые могут выполняться одновременно при использовании test.concurrent . Любой тест, превышающий этот предел, будет поставлен в очередь и выполнен после освобождения слота.

maxWorkers [номер | строка] #

Задает максимальное количество рабочих, которые пул рабочих будет порождать для выполнения тестов. В режиме одиночного запуска это значение по умолчанию равно количеству ядер, доступных на вашем компьютере, за вычетом одного для основного потока. В режиме слежения по умолчанию используется половина доступных ядер на вашем компьютере, чтобы Jest был ненавязчивым и не заставлял вашу машину останавливаться. Может быть полезно настроить это в средах с ограниченными ресурсами, таких как CI, но значения по умолчанию должны подходить для большинства случаев использования.

Для сред с переменными ЦП вы можете использовать процентную конфигурацию: "maxWorkers": "50%"

moduleDirectories [array ] #

По умолчанию: ["node_modules"]

Массив имен каталогов для рекурсивного поиска вверх от местоположения требуемого модуля. Установка этой опции переопределяет по умолчанию, если вы хотите по-прежнему искать node_modules для пакетов, включающих его вместе с любыми другими параметрами: ["node_modules", "bower_components"]

moduleFileExtensions [array ] #

По умолчанию: ["js", "jsx", "ts", "tsx", "json", "node"]

Массив расширений файлов, используемых вашими модулями.Если вам требуются модули без указания расширения файла, Jest будет искать эти расширения в порядке слева направо.

Мы рекомендуем размещать расширения, наиболее часто используемые в вашем проекте, слева, поэтому, если вы используете TypeScript, вы можете рассмотреть возможность перемещения «ts» и / или «tsx» в начало массива.

moduleNameMapper [объект <строка, строка | array >] #

По умолчанию: null

Сопоставление регулярных выражений с именами модулей или с массивами имен модулей, которые позволяют заглушить ресурсы, такие как изображения или стили, с помощью одного модуля.

Модули, сопоставленные псевдониму, по умолчанию не заблокированы, независимо от того, включено ли автоматическое отключение или нет.

Используйте строковый токен для ссылки на значение rootDir , если вы хотите использовать пути к файлам.

Кроме того, вы можете заменять захваченные группы регулярных выражений, используя нумерованные обратные ссылки.

Пример:

Порядок определения отображений имеет значение. Выкройки проверяются один за другим, пока один не подходит. Наиболее конкретное правило должно быть указано первым.$ , это может вызвать трудно обнаруживаемые ошибки. Например. relay заменит все модули, которые содержат relay в качестве подстроки в его имени: relay , react-relay и graphql-relay все будут указывать на вашу заглушку.

modulePathIgnorePatterns [array ] #

По умолчанию: []

Массив строк шаблонов регулярных выражений, которые сопоставляются со всеми путями модулей до того, как эти пути будут считаться «видимыми» для загрузчика модуля .Если путь к данному модулю соответствует любому из шаблонов, он не будет доступен для require () в тестовой среде.

Эти строки шаблона соответствуют полному пути. Используйте строковый токен , чтобы включить путь к корневому каталогу вашего проекта, чтобы предотвратить его случайное игнорирование всех ваших файлов в разных средах, которые могут иметь разные корневые каталоги. Пример: [" / build /"] .

modulePaths [array ] #

По умолчанию: []

Альтернативный API для установки переменной env NODE_PATH , modulePaths — это массив абсолютных путей к дополнительным местоположениям для поиска при разрешении модули.Используйте строковый токен , чтобы указать путь к корневому каталогу вашего проекта. Пример: [" / app /"] .

notify [boolean] #

По умолчанию: false

Активирует уведомления о результатах тестирования.

Осторожно: Jest использует node-notifier для отображения уведомлений на рабочем столе. В Windows он создает новую запись в меню «Пуск» при первом использовании и не отображает уведомление. Уведомления будут правильно отображаться при последующих запусках.

notifyMode [строка] #

По умолчанию: отказ-изменение

Задает режим уведомления.Требуется notify: true .

Modes #
  • всегда : всегда отправлять уведомление.
  • сбой : отправить уведомление, если тесты не пройдут.
  • успешно : отправить уведомление, когда тесты пройдут.
  • изменить : отправить уведомление при изменении статуса.
  • изменение успеха : отправить уведомление, когда тесты пройдены, или один раз, когда они не пройдут.
  • отказ-изменение : отправить уведомление, когда тесты не пройдут, или один раз, когда они пройдут.

предустановка [строка] #

По умолчанию: undefined

Предустановка, которая используется в качестве основы для конфигурации Jest. Пресет должен указывать на модуль npm, в корне которого находится файл jest-preset.json , jest-preset.js , jest-preset.cjs или jest-preset.mjs .

Например, этот пресет foo-bar / jest-preset.js будет сконфигурирован следующим образом:

Предустановки также могут относиться к путям файловой системы.

prettierPath [строка] #

По умолчанию: 'prettier'

Устанавливает путь к модулю узла prettier , используемому для обновления встроенных снимков.

проектов [массив <строка | ProjectConfig>] #

По умолчанию: undefined

Когда конфигурация projects предоставляется с массивом путей или глобальных шаблонов, Jest будет запускать тесты во всех указанных проектах одновременно.Это отлично подходит для монорепозиториев или при одновременной работе над несколькими проектами.

В этом примере конфигурации Jest будет запускаться в корневом каталоге, а также в каждой папке в каталоге примеров. Вы можете иметь неограниченное количество проектов, работающих в одном экземпляре Jest.

Функцию проектов также можно использовать для запуска нескольких конфигураций или нескольких бегунов. Для этого можно передать массив объектов конфигурации. Например, чтобы запустить и тесты, и ESLint (через jest-runner-eslint) при одном вызове Jest:

Примечание: при использовании многопроектного runner рекомендуется добавить displayName для каждого проекта.Это покажет displayName проекта рядом с его тестами.

репортеры [array ] #

По умолчанию: undefined

Используйте эту опцию конфигурации для добавления пользовательских репортеров в Jest. Пользовательский репортер — это класс, реализующий методы onRunStart , onTestStart , onTestResult , onRunComplete , которые будут вызываться при возникновении любого из этих событий.

Если указаны пользовательские репортеры, стандартные репортеры Jest будут переопределены. Чтобы сохранить репортеры по умолчанию, в качестве имени модуля можно передать default .

Это переопределит репортеры по умолчанию:

Это будет использовать настраиваемый репортер в дополнение к репортерам по умолчанию, которые предоставляет Jest:

Кроме того, настраиваемые репортеры можно настроить, передав объект options в качестве второго аргумента:

Пользовательские модули репортера должен определить класс, который принимает GlobalConfig и параметры репортера в качестве аргументов конструктора:

Пример репортера:

Пользовательские репортеры также могут заставить Jest выйти с кодом, отличным от 0, путем возврата ошибки из методов getLastError ()

Полный список методов и типов аргументов см. В интерфейсе Reporter в пакетах / jest-reporters / src / types.ts

resetMocks [boolean] #

По умолчанию: false

Автоматически сбрасывать фиктивное состояние перед каждым тестом. Эквивалентно вызову jest.resetAllMocks () перед каждым тестом. Это приведет к удалению поддельных реализаций любых моков, но не восстановит их первоначальную реализацию.

resetModules [логический] #

По умолчанию: false

По умолчанию каждый тестовый файл получает свой собственный независимый реестр модулей.Включение сброса Модули идут дальше и сбрасывают реестр модулей перед запуском каждого отдельного теста. Это полезно для изоляции модулей для каждого теста, чтобы состояние локального модуля не конфликтовало между тестами. Это можно сделать программно, используя jest.resetModules () .

преобразователь [строка] #

По умолчанию: undefined

Этот параметр позволяет использовать настраиваемый преобразователь. Этот преобразователь должен быть модулем узла, который экспортирует функцию, ожидающую строку в качестве первого аргумента пути для разрешения и объект со следующей структурой в качестве второго аргумента:

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

Примечание: defaultResolver, переданный в качестве опции, является резолвером Jest по умолчанию, который может быть полезен при написании собственного. Он принимает те же аргументы, что и ваш собственный, например (запрос, опции) .

Например, если вы хотите учитывать поле «browser» в Browserify, вы можете использовать следующую конфигурацию:

Объединив defaultResolver и packageFilter , мы можем реализовать «препроцессор» package.json это позволяет нам изменить способ разрешения модулей по умолчанию.Например, представьте, что мы хотим использовать поле «модуль» , если оно присутствует, в противном случае вернуться к «main» :

restoreMocks [boolean] #

По умолчанию: false

Автоматически восстановить макет состояние перед каждым тестом. Эквивалентно вызову jest.restoreAllMocks () перед каждым тестом. Это приведет к удалению поддельных реализаций любых моков и восстановлению их первоначальной реализации.

rootDir [строка] #

По умолчанию: корень каталога, содержащего ваш файл конфигурации Jest или пакет .json или pwd , если package.json не найден

Корневой каталог, в котором Jest должен сканировать тесты и модули. Если вы поместите свою конфигурацию Jest в свой package.json и хотите, чтобы корневой каталог был корнем вашего репо, значением этого параметра конфигурации по умолчанию будет каталог package.json .

Часто вам нужно установить это значение 'src' или 'lib' , в зависимости от того, где в вашем репозитории хранится код.

Обратите внимание, что использование '' в качестве строкового токена в любых других параметрах конфигурации на основе пути будет ссылаться на это значение. Так, например, если вы хотите, чтобы ваша запись конфигурации setupFiles указывала на файл env-setup.js в корне вашего проекта, вы можете установить для него значение [" / env-setup. js "] .

корни [array ] #

По умолчанию: [""]

Список путей к каталогам, которые Jest должен использовать для поиска файлов.

Бывают случаи, когда вы хотите, чтобы Jest выполнял поиск только в одном подкаталоге (например, в случаях, когда у вас есть каталог src / в вашем репо), но не позволяйте ему получить доступ к остальной части репо.

Примечание. В то время как rootDir в основном используется в качестве токена для повторного использования в других параметрах конфигурации, корни используются внутренними компонентами Jest для поиска тестовых файлов и исходных файлов . Это применимо также при поиске ручных макетов для модулей из node_modules ( __mocks__ должен находиться в одном из корней ).

Примечание. По умолчанию root имеет одну запись , но есть случаи, когда вы можете захотеть иметь несколько корней в одном проекте, например корни : [" / src / "," <корневой каталог> / tests / "] .

runner [строка] #

По умолчанию: "jest-runner"

Эта опция позволяет вам использовать пользовательский runner вместо тестового runner Jest по умолчанию. Примеры бегунов включают:

Примечание. Значение свойства runner может опускать префикс jest-runner- в имени пакета.

Чтобы написать средство выполнения тестов, экспортируйте класс, который принимает в конструкторе globalConfig и имеет метод runTests с сигнатурой:

Если вам нужно ограничить средство запуска теста только последовательным запуском вместо того, чтобы выполняться параллельно, ваш класс должен иметь свойство isSerial , которое должно быть установлено как true .

setupFiles [массив] #

По умолчанию: []

Список путей к модулям, которые запускают некоторый код для настройки или настройки среды тестирования.Каждый setupFile будет запускаться один раз для каждого тестового файла. Поскольку каждый тест выполняется в своей собственной среде, эти сценарии будут выполняться в тестовой среде непосредственно перед выполнением самого тестового кода.

Также стоит отметить, что setupFiles выполнит перед setupFilesAfterEnv .

setupFilesAfterEnv [array] #

По умолчанию: []

Список путей к модулям, которые запускают некоторый код для настройки или настройки среды тестирования перед выполнением каждого тестового файла в наборе.Поскольку setupFiles выполняется до установки среды тестирования в среде, этот файл сценария предоставляет вам возможность запустить некоторый код сразу после установки среды тестирования в среде.

Если вы хотите, чтобы путь относился к корневому каталогу вашего проекта, включите внутри строки пути, например " / a-configs-folder" .

Например, Jest поставляется с несколькими подключаемыми модулями для jasmine , которые работают путем обезьяньего исправления API jasmine.Если вы хотите добавить в микс еще больше плагинов жасмина (или, например, вам нужны специальные сопоставители для всего проекта), вы можете сделать это в этих модулях.

Примечание. setupTestFrameworkScriptFile устарел в пользу setupFilesAfterEnv .

Пример setupFilesAfterEnv массив в jest.config.js:

Пример jest.setup.js файл

slowTestThreshold [число] #

По умолчанию: 5

Количество секунд после который считается медленным и отражается в результатах как таковой.

snapshotResolver [string] #

По умолчанию: undefined

Путь к модулю, который может разрешить test <-> путь к моментальному снимку. Этот параметр конфигурации позволяет вам настроить, где Jest хранит файлы моментальных снимков на диске.

Пример модуля преобразователя моментальных снимков:

snapshotSerializers [array ] #

По умолчанию: []

Список путей к модулям сериализатора моментальных снимков, которые Jest должен использовать для тестирования моментальных снимков.

Jest имеет сериализаторы по умолчанию для встроенных типов JavaScript, элементов HTML (Jest 20.0.0+), ImmutableJS (Jest 20.0.0+) и для элементов React. Дополнительную информацию см. В руководстве по тестированию снимков.

Пример модуля сериализатора:

принтер — это функция, которая сериализует значение, используя существующие плагины.

Чтобы использовать my-serializer-module в качестве сериализатора, конфигурация будет следующей:

Наконец, тесты будут выглядеть следующим образом:

Визуализированный снимок:

Чтобы сделать зависимость явной вместо неявной, вы можете позвонить ожидать.addSnapshotSerializer , чтобы добавить модуль для отдельного тестового файла вместо добавления его пути к snapshotSerializers в конфигурации Jest.

Подробнее об API сериализаторов можно найти здесь.

testEnvironment [строка] #

По умолчанию: «узел»

Тестовая среда, которая будет использоваться для тестирования. Средой по умолчанию в Jest является среда Node.js. Если вы создаете веб-приложение, вы можете использовать среду, подобную браузеру, через jsdom .

Добавив док-блок @ jest-environment вверху файла, вы можете указать другую среду, которая будет использоваться для всех тестов в этом файле:

Вы можете создать свой собственный модуль, который будет использоваться для настройки тестовая среда. Модуль должен экспортировать класс с методами setup , teardown и getVmContext . Вы также можете передавать переменные из этого модуля в свои наборы тестов, назначив их объекту this.global — это сделает их доступными в ваших наборах тестов в качестве глобальных переменных.

Класс может дополнительно предоставить асинхронный метод handleTestEvent для привязки к событиям, запускаемым jest-circus . Обычно программа запуска тестов jest-circus приостанавливается до тех пор, пока не будет выполнено обещание, возвращенное из handleTestEvent , , за исключением следующих событий : start_describe_definition , finish_describe_definition , add_hook , add_test или error для получения актуального списка вы можете посмотреть тип SyncEvent в определениях типов).Это вызвано причинами обратной совместимости и сигнатурой process.on ('unhandledRejection', callback) , но обычно это не должно быть проблемой для большинства случаев использования.

Любые прагмы docblock в тестовых файлах будут переданы в конструктор среды и могут использоваться для настройки каждого теста. Если прагма не имеет значения, она будет присутствовать в объекте со значением, установленным в пустую строку. Если прагма отсутствует, она не будет присутствовать в объекте.

Чтобы использовать этот класс в качестве настраиваемой среды, укажите его полный путь в проекте. Например, если ваш класс хранится в my-custom-environment.js в некоторой подпапке вашего проекта, то аннотация может выглядеть так:

Примечание: TestEnvironment изолирована. Каждый набор тестов запускает установку / разборку в своей собственной TestEnvironment.

Пример:

testEnvironmentOptions [Object] #

По умолчанию: {}

Параметры тестовой среды, которые будут переданы в testEnvironment .Соответствующие варианты зависят от окружающей среды. Например, вы можете переопределить параметры, данные jsdom, такие как {userAgent: "Agent / 007"} .

testFailureExitCode [число] #

По умолчанию: 1

Код выхода Jest возвращается при ошибке теста.

Примечание. Это не меняет код выхода в случае ошибок Jest (например, неверной конфигурации).

testMatch [array ] #

(по умолчанию: ["** / __ tests __ / ** / *.[jt] s? (x) "," ** /? (*.) + (spec | test). [jt] s? (x) "] )

Шаблоны глобусов, которые Jest использует для обнаружения тестовых файлов. По умолчанию он ищет файлы .js , .jsx , .ts и .tsx внутри папок __tests__ , а также любые файлы с суффиксом .test или .spec . (например, Component.test.js или Component.spec.js .) Он также найдет файлы с именами test.js или spec.js .

Подробную информацию о шаблонах, которые вы можете указать, см. В пакете micromatch.

См. Также testRegex [строка | array ], но учтите, что вы не можете указать обе опции.

Примечание. Каждый шаблон глобуса применяется в том порядке, в котором они указаны в конфигурации. (Например, ["! ** / __ fixtures __ / **", "** / __ tests __ / ** / *. Js"] не будет исключать __fixtures__ , потому что отрицание перезаписывается вторым шаблоном. заставить отрицательный глобус работать в этом примере, он должен появиться после ** / __ tests __ / ** / *.js .)

testPathIgnorePatterns [array ] #

По умолчанию: ["/ node_modules /"]

Массив строк шаблонов регулярного выражения, которые сопоставляются со всеми тестовыми путями перед выполнением теста. Если тестовый путь соответствует любому из шаблонов, он будет пропущен.

Эти строки шаблона соответствуют полному пути. Используйте строковый токен , чтобы включить путь к корневому каталогу вашего проекта, чтобы предотвратить его случайное игнорирование всех ваших файлов в разных средах, которые могут иметь разные корневые каталоги.Пример: ["<корневой каталог> / build /", "<корневой каталог> / node_modules /"] .

testRegex [строка | array ] #

По умолчанию: (/__tests__/.*|(\\.|/)(test|spec))\\.[jt providedsx?$

Шаблон или шаблоны, которые Jest использует для обнаруживать тестовые файлы. По умолчанию он ищет файлы .js , .jsx , .ts и .tsx внутри папок __tests__ , а также любые файлы с суффиксом .test или .spec (например, Component.test.js или Component.spec.js ). Он также найдет файлы с именами test.js или spec.js . См. Также testMatch [array ], но учтите, что вы не можете указать обе опции.

Ниже представлена ​​визуализация регулярного выражения по умолчанию:

Примечание: testRegex попытается обнаружить тестовые файлы, используя абсолютный путь к файлу , поэтому при наличии папки с соответствующим именем будут запускаться все файлы как тесты

testResultsProcessor [строка] #

По умолчанию: undefined

Этот параметр позволяет использовать пользовательский обработчик результатов.Этот процессор должен быть модулем узла, который экспортирует функцию, ожидающую объект со следующей структурой в качестве первого аргумента, и возвращает его:

testRunner [строка] #

По умолчанию: jest-circus / runner

Этот параметр позволяет использовать настраиваемую программу запуска тестов. По умолчанию - jest-circus . Пользовательский исполнитель тестов может быть предоставлен путем указания пути к реализации средства выполнения тестов.

Модуль запуска тестов должен экспортировать функцию со следующей сигнатурой:

Пример такой функции можно найти в нашем пакете запуска тестов jasmine2 по умолчанию.

testSequencer [строка] #

По умолчанию: @ jest / test-Sequencer

Эта опция позволяет вам использовать собственный секвенсор вместо стандартного Jest. sort может дополнительно возвращать Promise.

Пример:

Сортировка тестового пути по алфавиту.

Используйте его в файле конфигурации Jest следующим образом:

testTimeout [число] #

По умолчанию: 5000

Тайм-аут теста по умолчанию в миллисекундах.

testURL [строка] #

По умолчанию: http: // localhost

Этот параметр устанавливает URL-адрес для среды jsdom. Это отражено в таких свойствах, как location.href .

таймеры [строка] #

По умолчанию: real

Установка этого значения на fake или modern позволяет использовать поддельные таймеры для таких функций, как setTimeout . Поддельные таймеры полезны, когда часть кода устанавливает длительный тайм-аут, которого мы не хотим ждать в тесте.

Если значение равно legacy , в качестве реализации будет использоваться старая реализация вместо реализации, поддерживаемой @ sinonjs / fake-timers .

преобразование [объект <строка, pathToTransformer | [pathToTransformer, object]>] #

По умолчанию: {"\\. [jt] sx? $": "babel-jest"}

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

Примеры таких компиляторов включают:

Вы можете передать конфигурацию преобразователю, например {filePattern: ['path-to-transformer', {options}]} Например, чтобы настроить babel-jest на нестандартное поведение , {"\\.js $ ": ['babel-jest', {rootMode:" upward "}]}

Примечание: преобразователь запускается только один раз для каждого файла, если файл не изменился. Во время разработки преобразователя это может быть полезно для запуска Jest с --no-cache для частого удаления кеша Jest.

Примечание: при добавлении дополнительных преобразователей кода это перезапишет конфигурацию по умолчанию, и babel-jest больше не загружается автоматически. чтобы использовать его для компиляции JavaScript или Typescript, он должен быть явно определен путем добавления {"\\.[jt] sx? $ ":" babel-jest "} в свойство transform. См. подключаемый модуль babel-jest

Преобразователь должен быть объектом как минимум с функцией процесса , также рекомендуется включать getCacheKey function. Если ваш преобразователь написан на ESM, у вас должен быть экспорт по умолчанию с этим объектом.

Если тесты написаны с использованием собственного ESM, преобразователь может экспортировать processAsync и getCacheKeyAsync вместо или в дополнение к синхронному варианты.\\\ /] + $ "]

Массив строк шаблона регулярного выражения, которые сопоставляются со всеми путями исходного файла перед преобразованием. Если путь к файлу соответствует любому из шаблонов, он не будет преобразован.

Эти строки шаблона совпадение с полным путем.Используйте строковый токен , чтобы включить путь к корневому каталогу вашего проекта, чтобы предотвратить его случайное игнорирование всех ваших файлов в разных средах, которые могут иметь разные корневые каталоги.

Пример: [" / bower_components /", " / node_modules /"] .

Иногда бывает (особенно в проектах React Native или TypeScript), что сторонние модули публикуются как нетранспортированные. Поскольку все файлы внутри node_modules не преобразуются по умолчанию, Jest не распознает код в этих модулях, что приводит к синтаксическим ошибкам. Чтобы преодолеть это, вы можете использовать transformIgnorePatterns , чтобы разрешить транспиляцию таких модулей.Вы найдете хороший пример этого варианта использования в React Native Guide.

unmockedModulePathPatterns [array ] #

По умолчанию: []

Массив строк шаблонов регулярных выражений, которые сопоставляются со всеми модулями до того, как загрузчик модулей автоматически вернет для них имитацию. Если путь к модулю соответствует любому из шаблонов в этом списке, он не будет автоматически имитировать загрузчик модуля.

Это полезно для некоторых часто используемых «служебных» модулей, которые почти всегда используются в качестве деталей реализации почти все время (например, подчеркивание / нижнее тире и т. Д.).Обычно рекомендуется делать этот список как можно меньшим и всегда использовать явные вызовы jest.mock () / jest.unmock () в отдельных тестах. Явная настройка для каждого теста намного проще для других читателей теста, чтобы рассуждать о среде, в которой будет выполняться тест.

Можно переопределить этот параметр в отдельных тестах, явно вызвав jest.mock () вверху тестового файла.

подробный [логический] #

По умолчанию: false

Указывает, следует ли сообщать о каждом отдельном тесте во время выполнения.Все ошибки также будут отображаться внизу после выполнения. Обратите внимание, что если запущен только один тестовый файл, по умолчанию будет true .

watchPathIgnorePatterns [array ] #

По умолчанию: []

Массив шаблонов RegExp, которые сопоставляются со всеми путями к исходным файлам перед повторным запуском тестов в режиме наблюдения. Если путь к файлу соответствует любому из шаблонов, при его обновлении повторный запуск тестов не запускается.

Эти шаблоны соответствуют полному пути. Используйте строковый токен , чтобы включить путь к корневому каталогу вашего проекта, чтобы предотвратить его случайное игнорирование всех ваших файлов в разных средах, которые могут иметь разные корневые каталоги. Пример: [" / node_modules /"] .

Даже если здесь ничего не указано, наблюдатель будет игнорировать изменения любых скрытых файлов и каталогов, то есть файлов и папок, которые начинаются с точки (.).

watchPlugins [массив <строка | [строка, объект]>] #

По умолчанию: []

Этот параметр позволяет использовать настраиваемые плагины для наблюдения. Подробнее о плагинах для часов читайте здесь.

Примеры подключаемых модулей для наблюдения:

Примечание. Значения в значении свойства watchPlugins могут опускать префикс jest-watch- в имени пакета.

watchman [логическое] #

По умолчанию: true

Следует ли использовать watchman для сканирования файлов.

// [строка] #

Нет по умолчанию

Эта опция позволяет комментарии в package.json . Включите текст комментария как значение этого ключа в любое место в package.json .

Пример:

Учебное пособие по Node.js и TypeScript: защита Express API

Начиная с этой главы?

Клонируйте репозиторий приложения и просмотрите ветку build-api :

  git clone [email protected]: auth0-blog / menu-api-express-ts.мерзавец \
меню-api \
--branch build-api  

Сделать папку проекта вашим текущим каталогом:

  cd menu-api  

Затем установите зависимости проекта:

  npm i  

Наконец, создайте .env скрытый файл:

  touch .env  

Заполните .env следующим:

  PORT = 7000  

Запустите проект, выполнив следующую команду:

  npm run dev  

В сборке API с Node.js и TypeScript Tutorial, вы узнали, как создать API с помощью Express, веб-фреймворка Node.js и TypeScript, языка с открытым исходным кодом, основанного на JavaScript. Вы узнали, как определять модели данных, создавать службы данных и быстро создавать модульные конечные точки.

Теперь это руководство покажет вам, как защитить API с помощью Auth0 . Чтобы увидеть свой API в действии, вы будете использовать рабочий клиент под названием «WHATABYTE Dashboard», вдохновленный элегантным веб-плеером от Spotify:

Одно из требований для этого проекта — только авторизованные пользователи могут писать записи в магазин .Чтобы быстро и безопасно достичь этого, вы можете использовать Auth0 для управления учетными данными пользователя вашего приложения.

Настройка службы авторизации

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

Auth0 — это гибкое решение для добавления сервисов аутентификации и авторизации в ваши приложения. Ваша команда и организация могут избежать затрат, времени и рисков, связанных с созданием собственного решения для аутентификации и авторизации пользователей.Мы предлагаем множество руководств и SDK, чтобы вы могли начать работу и легко интегрировать Auth0 в свой стек.

После создания учетной записи вы создадите клиента Auth0, который представляет собой контейнер, который Auth0 использует для изолированного хранения конфигурации вашей службы идентификации и ваших пользователей — ни один другой клиент Auth0 не сможет заглянуть в ваш клиент или получить к нему доступ. Это похоже на то, что вы снимаетесь в многоквартирном доме. Auth0 присматривает за зданием, а квартира — все, что вам нужно, чтобы жить и настраивать. Однако каждая квартира полностью изолирована (нет окон, звуконепроницаемых стен и т. Д.).), чтобы соседи не могли нарушить вашу конфиденциальность.

После создания вашего клиента вам необходимо создать регистр API с Auth0, который представляет собой API, который вы определяете в своем клиенте Auth0 и который вы можете использовать из своих приложений для обработки запросов аутентификации и авторизации.

После создания учетной записи перейдите в раздел API на панели инструментов Auth0 и нажмите кнопку Create API .

Затем в форме, которую показывает Auth0:

  • Добавьте Name в свой API: Menu API .

  • Установите для идентификатора значение https://menu-api.example.com .

  • Оставьте алгоритм подписи RS256 , так как это лучший вариант с точки зрения безопасности.

Идентификаторы — это уникальные строки, которые помогают Auth0 различать ваши API. Мы рекомендуем использовать URL-адреса, поскольку они позволяют предсказуемо создавать уникальные идентификаторы; однако Auth0 никогда не вызывает эти URL-адреса.

Установив эти значения, нажмите кнопку Create .

Вашему API требуются некоторые конфигурационные переменные для идентификации себя с Auth0: значение Audience и Domain . Лучше всего хранить эти значения в файле .env вашего проекта.

Откройте .env и добавьте к нему следующие ключи:

  PORT = 7000
AUTH0_AUDIENCE =
AUTH0_DOMAIN =  

Вернитесь на страницу Auth0 API, и выполните следующие действия, чтобы получить Auth0 Audience :

  1. Щелкните вкладку «Настройки» .

  2. Найдите поле «Идентификатор» и скопируйте его значение.

  3. Вставьте значение «Идентификатор» как значение AUTH0_AUDIENCE в .env .

Теперь, выполните следующие действия, чтобы получить значение домена Auth0. :

  1. Щелкните вкладку «Тест» .
  2. Найдите раздел под названием «Запрос Auth0 для токенов из моего приложения» .
  3. Щелкните вкладку cURL , чтобы отобразить фиктивный запрос POST .
  4. Скопируйте свой домен Auth0, который является частью значения параметра --url : tenant-name.region.auth0.com .
  5. Вставьте значение домена Auth0 как значение AUTH0_DOMAIN в .env .

Советы по получению домена Auth0

  • Домен Auth0 — это подстрока между протоколом https: // и путем / oauth / token .

  • Домен Auth0 следует этому шаблону: имя-арендатора.region.auth0.com .

  • Поддомен региона ( au , us или eu ) является необязательным. В некоторых доменах Auth0 его нет.

  • Нажмите на изображение выше, если у вас есть какие-либо сомнения относительно того, как получить значение домена Auth0 .

Перезапустите сервер, чтобы Express смог распознать изменения, которые вы только что внесли в .env . Остановите запущенный процесс и снова выполните npm run dev .

Создание промежуточного программного обеспечения для аутентификации

Вы будете полагаться на функцию промежуточного программного обеспечения для защиты конечной точки Express API. Express выполнит функцию промежуточного программного обеспечения авторизации до того, как выполнит функцию обратного вызова контроллера, который обрабатывает запрос.

Вы можете использовать два шаблона для интеграции ваших конечных точек с функцией промежуточного программного обеспечения авторизации.

Первый вариант — «внедрить» функцию промежуточного программного обеспечения авторизации в контроллер следующим образом:

  itemsRouter.Почта(
  "/",
  authorizationFunction,
  async (req: Request, res: Response) => {
    
  }
);  

Здесь Express вызывает authorizationFunction () перед функцией обработчика маршрута itemsRouter.post . В свою очередь, бизнес-логика в рамках авторизации Функция может выполнять две задачи:

(a) вызывать следующую функцию в цепочке промежуточного программного обеспечения, функцию обработчика маршрутизатора, если она может определить, что пользователь имеет разрешение на доступ к ресурсу. или

(b) закрыть цикл запрос-ответ, ответив сообщением 401 Unauthorized , которое не позволяет вашему API выполнить обработчик маршрута.

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

В качестве альтернативы вы можете отделить общедоступные контроллеры от защищенных контроллеров, используя промежуточное программное обеспечение авторизации в качестве границы между группами. Например, в маршрутизаторе Express вы можете сделать следующее:

 

itemsRouter.получать(...);



itemsRouter.use (authorizationFunction);

itemsRouter.post (...);
itemsRouter.put (...);
itemsRouter.delete (...);  

Таким образом, клиентские приложения могут получить доступ к конечной точке GET без предъявления каких-либо «подтверждений авторизации» — это общедоступная конечная точка .

Однако клиентские запросы могут получить доступ только к конечным точкам, которые вы определяете после того, как ваше приложение смонтирует authorizationFunction в itemsRouter , если authorizationFunction может определить, что клиент, выполняющий запрос конечной точки , имеет авторизацию для доступа к нему .Для этого API Auth0 предоставляет доказательство авторизации, упомянутое в форме веб-токена JSON (JWT), называемого токеном доступа .

JWT определяет компактный и автономный способ безопасной передачи информации между сторонами в виде объекта JSON. Эту информацию можно проверить и доверять, поскольку она имеет цифровую подпись, что делает JWT полезными для выполнения авторизации.

После того, как пользователь входит в систему с помощью клиентского приложения, Auth0 предоставляет клиенту токен доступа, который определяет ресурсы, к которым у клиента есть разрешение на доступ или управление с помощью этого токена.Маркер доступа определяет, что пользователи могут делать в вашем API в объекте JSON, который он инкапсулирует. Таким образом, клиент должен включать токен доступа в каждый последующий запрос, который он делает к защищенной конечной точке API.

Для этого приложения вы будете использовать метод секционирования, поскольку вам необходимо защитить все конечные точки, которые записывают данные в хранилище.

Установка зависимостей авторизации

Чтобы создать функцию промежуточного ПО для авторизации, вам необходимо установить эти два пакета:

  npm i express-jwt jwks-rsa  

Вот что эти пакеты делают для вас:

  • express -jwt : проверяет уровень авторизации HTTP-запросов с использованием токенов JWT в вашем Node.js-приложение.

  • jwks-rsa : библиотека для получения ключей подписи RSA из конечной точки JWKS (JSON Web Key Set).

Поскольку вы работаете над проектом TypeScript, вам также потребуются определения типов для этих пакетов; однако только пакет express-jwt доступен в пространстве имен @types npm:

  npm i -D @ types / express-jwt  

Необходимая вспомогательная функция из jwks-rsa пакет прост и не требует строгой типизации.

Затем создайте файл для определения вашей функции промежуточного программного обеспечения авторизации:

  touch src / middleware / authz.middleware.ts  

Заполните src / middleware / authz.middleware.ts следующим образом:

 

импортировать jwt из "express-jwt";
импортировать jwksRsa из "jwks-rsa";
import * as dotenv из "dotenv";

dotenv.config ();

экспорт const checkJwt = jwt ({
  secret: jwksRsa.expressJwtSecret ({
    кеш: правда,
    rateLimit: истина,
    jwksRequestsPerMinute: 5,
    jwksUri: `https: // $ {process.env.AUTH0_DOMAIN} /. хорошо известный / jwks.json`
  }),

  
  аудитория: process.env.AUTH0_AUDIENCE,
  эмитент: `https: // $ {process.env.AUTH0_DOMAIN} /`,
  алгоритмы: ["RS256"]
});  

Когда вы вызываете функцию checkJwt , она вызывает функцию jwt , проверяя, что любой веб-токен JSON (JWT), присутствующий в полезной нагрузке запроса для авторизации запроса, правильно сформирован и действителен. Auth0 определяет действительность JWT. Таким образом, вы передаете функции jwt некоторые переменные, чтобы помочь ей связаться с Auth0 и представить ей всю необходимую информацию JWT:

  • Аудитория и эмитент JWT.Вы определили эти значения в файле .env . Express загрузил этот модуль с помощью dotenv.config () .

  • Алгоритмы , , используемые для подписи JWT.

  • Секрет , используемый для подписи JWT.

Чтобы получить секрет, вам необходимо проделать некоторую дополнительную работу: вы используете вспомогательную функцию expressJwtSecret из библиотеки jwks-rsa для запроса конечной точки набора веб-ключей JSON (JWKS) вашего клиента Auth0.Эта конечная точка имеет набор ключей, содержащих открытые ключи, которые ваше приложение может использовать для проверки любого веб-токена JSON (JWT), выданного сервером авторизации и подписанного с использованием алгоритма подписи RS256.

Функция checkJwt неявно принимает запрос, req , и ответ, res , объект из Express, а также функцию next () , которую она может использовать для вызова следующей функции промежуточного программного обеспечения в цепь.

Все, что осталось сделать, это смонтировать функцию промежуточного программного обеспечения checkJwt , прежде чем монтировать конечные точки записи itemsRouter .

Откройте src / items / items.router.ts и импортируйте checkJwt в разделе Требуемые внешние модули и интерфейсы :

 

импорт экспресс, {запрос, ответ} из "экспресс";
import * как ItemService из "./items.service";
импортировать {BaseItem, Item} из "./item.interface";

импортировать {checkJwt} из "../middleware/authz.middleware";  

Затем в разделе «Определения контроллеров » найдите определение конечной точки POST items и прямо над ним добавьте следующий код для монтирования промежуточного программного обеспечения авторизации, itemsRouter.используйте (checkJwt) :

 


itemsRouter.get (...);



itemsRouter.get (...);



itemsRouter.use (checkJwt);



itemsRouter.post (...);



itemsRouter.put (...);



itemsRouter.delete (...);  

Чтобы проверить, защищает ли Express ваши конечные точки записи, выполните в терминале следующий запрос:

  curl -X POST -H 'Content-Type: application / json' -d '{
  "name": "Салат",
  «цена»: 499,
  "description": "Свежий",
  "изображение": "https://cdn.auth0.com/blog/whatabyte/salad-sm.png "
} 'http: // localhost: 7000 / api / menu / items -i  

Сервер отвечает статусом ответа HTTP / 1.1 401 Unauthorized и сообщением Не найден токен авторизации , подтверждающий, что вы пишете конечные точки защищены. Для доступа к ним вам понадобится JWT, выданный Auth0. Самый быстрый способ получить этот токен — использовать клиента, как и любой из ваших пользователей.

Зарегистрируйте клиентское приложение с Auth0

Вам необходимо клиентское приложение, чтобы имитировать взаимодействие конечного пользователя с вашим API и увидеть его безопасность в действии.Чтобы сделать эту симуляцию более увлекательной и увлекательной, вы будете использовать WHATABYTE Dashboard, демонстрационное клиентское приложение, которое позволяет вам управлять элементами меню ресторана. Вы создадите пользователя с Auth0, войдите в систему и получите доступ к страницам, которые делают запросы к вашим конечным точкам API под капотом.

Чтобы такое взаимодействие с конечным пользователем произошло, вам необходимо создать регистр одностраничного приложения с Auth0. Этот регистр предоставит вам значения конфигурации, необходимые для подключения демонстрационного клиентского приложения с Auth0, а именно: домен Auth0 и идентификатор клиента Auth0.После настройки клиентское приложение может взаимодействовать с сервером аутентификации Auth0 и получать токены доступа для пользователей, вошедших в систему.

Процесс создания реестра одностраничного приложения Auth0 прост:

  • Откройте раздел Auth0 Applications на панели инструментов Auth0.

  • Нажмите кнопку Create Application .

  • Укажите значение Name , например WHATABYTE Demo Client .

  • Выберите одностраничные веб-приложения в качестве типа приложения .

  • Нажмите кнопку Create .

Загрузится новая страница с подробной информацией о вашем реестре приложения Auth0. Щелкните вкладку Настройки , чтобы получить доступ к его значениям конфигурации.

Затем посетите https://dashboard.whatabyte.app/ , чтобы открыть демонстрационное клиентское приложение WHATABYTE Dashboard.

Если вы не находитесь на странице Auth0 Demo Settings , щелкните вкладку «Настройки» на левой панели навигации, а затем нажмите кнопку «Изменить».

Включите функции аутентификации демонстрационного приложения. Затем используйте значения конфигурации, представленные на странице «Настройки» вашего приложения Auth0, чтобы заполнить значения Auth0 Domain и Auth0 Client ID в форме демонстрационных настроек:

Для значения Auth0 API Audience используйте https://menu-api.example.com , который является идентификатором API МЕНЮ, который вы зарегистрировали с помощью Auth0 ранее в руководстве.

Для значения Auth0 Callback URL используйте https: // dashboard.whatabyte.app/home . В следующем разделе вы узнаете, как Auth0 использует это значение обратного вызова.

Нажмите кнопку Сохранить под формой. Панель мониторинга WHATABYTE является клиентом вашего сервера API. Чтобы проверить это соединение, щелкните вкладку Menu и посмотрите, как она заполняется элементами меню, которые вы определили в своем магазине API.

Подключите клиентское приложение с Auth0

Вернитесь на вкладку Настройки страницы реестра приложения Auth0 и обновите следующие поля:

Разрешенные URL-адреса обратного вызова

Используйте значение Auth0 URL-адрес обратного вызова из Auth0 Форма Demo Settings , https: // дашборд.whatabyte.app/home .

После аутентификации пользователя Auth0 выполняет обратный вызов только по любому из URL-адресов, перечисленных в этом поле. Вы можете указать несколько действительных URL-адресов, разделив их запятыми (обычно для обработки различных сред, таких как QA или тестирование). Обязательно укажите протокол: http: // или https: // ; в противном случае в некоторых случаях обратный вызов может завершиться ошибкой.

Разрешенное веб-происхождение

Используйте https://dashboard.whatabyte.app .

Клиентское приложение будет делать внутренние запросы к URL-адресу Auth0 для обработки запросов аутентификации.Таким образом, вам необходимо добавить URL-адрес источника вашего приложения, чтобы избежать проблем с совместным использованием ресурсов между источниками (CORS).

Разрешенные URL-адреса для выхода

Используйте https://dashboard.whatabyte.app/home .

Это поле содержит набор URL-адресов, на которые Auth0 может перенаправить после выхода пользователя из вашего приложения. Конфигурация демо-клиента по умолчанию использует указанное значение для перенаправления пользователей.

Установив эти значения, вы можете прокрутить страницу «Настройки» вниз и нажать кнопку Сохранить изменения .

Войти

В демонстрационном клиенте нажмите кнопку Войти . Клиент перенаправит вас на страницу универсального входа Auth0 для входа или регистрации. Поскольку это может быть первый пользователь, которого вы добавляете в Auth0, перейдите по ссылке Sign Up внизу формы. Затем укажите адрес электронной почты и пароль для регистрации нового пользователя.

После входа в систему пользовательский интерфейс демонстрационного клиента изменится:

Щелкните вкладку пользователя, чтобы увидеть страницу профиля с вашим именем или адресом электронной почты в качестве заголовка и изображением профиля — если вы вошли с помощью Google:

Демо-клиент обслуживает три типа пользователей:

  • Неаутентифицированные посетители : любой посетитель, который не вошел в систему — в некоторых литературах этот тип пользователей может упоминаться как «гость» или «анонимный» .

  • Аутентифицированные пользователи : любой посетитель, который успешно вошел в систему.

  • Административные пользователи : любой аутентифицированный пользователь с ролью menu-admin .

Конечной целью этого руководства является использование роли menu-admin и связанных с ней разрешений в качестве артефактов управления доступом. План состоит в том, чтобы разрешить только администраторам создавать, обновлять и удалять пункты меню в WHATABYTE Dashboard. В разделе «Управление доступом на основе ролей» (RBAC) этого руководства вы создадите роль menu-admin , свяжете с ней разрешения и назначите ее новому пользователю, которого вы создадите через панель Auth0 Dashboard.

Однако вы начнете с защиты конечных точек записи API от неаутентифицированных посетителей.

Поэкспериментируйте с демо-клиентом:

  • Добавьте элементы, нажав кнопку Добавить элемент , расположенную в правом верхнем углу страницы «Меню» .

  • Щелкните элементы и попробуйте отредактировать или удалить их.

Вы можете выполнять любые операции чтения или записи прямо сейчас.

Упражнение по безопасности: проверьте защиту конечной точки.

Выйдите из демонстрационного приложения.

Щелкните вкладку Settings на левой панели навигации демонстрационного клиента. Затем нажмите кнопку Изменить .

Загрузится страница «Auth0 Demo Settings» . Отключите функции аутентификации:

Нажмите кнопку Сохранить .

После того, как демонстрационное приложение загрузится снова, щелкните вкладку Menu . Вы заметите, что теперь отображается кнопка Добавить элемент . В этом режиме демонстрационный клиент позволяет вам получить доступ к элементам пользовательского интерфейса, которые отправляют запросы к вашим конечным точкам записи API, как неаутентифицированный посетитель .Таким образом, эти запросы не будут включать токен доступа. Если ваша безопасность API работает правильно, она должна отклонить эти запросы.

Нажмите кнопку Добавить элемент , чтобы открыть предварительно заполненную форму, и нажмите кнопку Сохранить . Вы получите сообщение об ошибке: Токен авторизации не найден :

Успешно! Ваш сервер Express API эффективно защищает ваши конечные точки записи от несанкционированных запросов. В этом контексте только аутентифицированные пользователи имеют право доступа к конечным точкам записи API.

Нажмите кнопку Отмена на странице «Добавить пункт меню» . «Пункты меню» загружаются снова. Щелкните по элементу «Бургер» и попробуйте его отредактировать или удалить.

Эти два действия также завершатся ошибкой:

Вы проверили, что Express правильно защищает ваши конечные точки создания, обновления и удаления, завершая это короткое упражнение.

Чтобы продолжить работу с оставшейся частью этого руководства, повторно включите демонстрационные функции аутентификации клиента.Щелкните вкладку Settings и нажмите кнопку Modify . Откроется страница «Auth0 Demo Settings» . Включите функции аутентификации, введите необходимое значение и нажмите кнопку Сохранить .

Настройка управления доступом на основе ролей (RBAC)

Ваш сервер API защищает ваши конечные точки записи, но любой аутентифицированный пользователь может изменять элементы меню. Этот сценарий далек от идеала, поскольку, например, вы не хотите, чтобы постоянные клиенты меняли цену на товар.Таким образом, вам нужен механизм для ограничения доступа к вашим ресурсам API и демонстрации того, что аутентификация — это не то же самое, что авторизация. Однако, если все, что вы хотите сейчас, — это ограничить доступ к API только зарегистрированным пользователям, вы добились этого, и все готово.

Простой способ реализовать контроль доступа — создать набор разрешений на запись и связать их с ролью menu-admin , которую вы назначаете только избранным пользователям. Таким образом, только избранным пользователям разрешено изменять ресурсы в вашем API.Следовательно, ваш сервер должен принудительно выполнять проверку роли на каждой конечной точке записи API, чтобы предотвратить неавторизованный доступ .

Повторим еще раз: аутентификации недостаточно для авторизации на запись данных в хранилище.

Описанная выше практика известна как управление доступом на основе ролей (RBAC), которое вы можете быстро реализовать для своего API с помощью панели инструментов Auth0. Вы можете реализовать RBAC и принудительно использовать его на своем сервере следующим образом:

На стороне Auth0

  • Создайте разрешения для API меню, созданного ранее.

  • Создайте роль с именем menu-admin .

  • Назначьте разрешения из API меню роли menu-admin .

  • Назначьте пользователю роль администратора меню .

  • Добавьте разрешения роли menu-admin к токену доступа, созданному для пользователей с ролью при входе в систему.

На стороне сервера

  • Определите разрешения роли menu-admin в TypeScript перечисление .

  • Определите разрешения, необходимые для доступа к конечной точке, передав значения разрешений в качестве аргументов функции промежуточного программного обеспечения авторизации, которую Express вызывает перед обработчиком маршрута конечной точки.

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

Как видите, реализация авторизации — это сложный процесс, который включает в себя много шагов.Любые ошибки или упущения в процессе внедрения могут подвергнуть API риску взлома. К счастью, вы можете делегировать создание и обслуживание разрешений, ролей и пользователей Auth0 и сосредоточиться только на обеспечении авторизации на вашем сервере.

С четко очерченным планом, приступим.

Определите разрешения для API

Откройте страницу API на панели инструментов Auth0 и выберите меню API , которое вы создали ранее.

На странице API меню щелкните вкладку Permissions и создайте три разрешения, заполнив каждую строку следующим образом (кнопка + Add добавляет новую строку):

  • create: items : Create menu элементы

  • обновление: элементы : элементы меню обновления

  • удаление: элементы : удаление элементов меню

Затем вам необходимо настроить Auth0 для принудительной авторизации управления доступом на основе ролей (RBAC) для API меню.Щелкните вкладку Settings и прокрутите вниз, пока не увидите раздел RBAC Settings . Используйте переключатель рядом с Включить RBAC , чтобы включить его, что заставляет Auth0 оценивать политики авторизации RBAC во время транзакции входа пользователя.

Затем включите Добавить разрешения в токене доступа , чтобы добавить свойство permissions к токену доступа, созданному Auth0 при входе пользователя в систему. Свойство permissions представляет собой пару «ключ-значение», известную как утверждение токена . .Наличие этого утверждения критически важно для реализации RBAC на вашем сервере API.

После включения этих параметров не забудьте нажать кнопку Сохранить .

Создание ролей

Откройте страницу ролей на панели инструментов Auth0 и нажмите кнопку Create Role . Заполните всплывающую форму следующим образом:

После этого нажмите кнопку Create , чтобы завершить создание роли.

Теперь вам нужно связать созданные вами разрешения с этой ролью, сопоставив ее с ресурсами вашего API.Щелкните вкладку Permissions на странице ролей. Оказавшись там, нажмите кнопку Добавить разрешения .

В появившемся диалоговом окне выберите Menu API из раскрывающегося списка и выберите все поля в разделе Scopes . Как только это будет сделано, нажмите кнопку Добавить разрешения . Вы вернулись на страницу роли menu-admin , на которой перечислены все связанные с ней разрешения.

Область — это термин, используемый OAuth 2.0 для определения ограничений на объем доступа, который вы можете предоставить токену доступа. По сути, разрешения определяют область действия токена доступа.

Получить роли пользователей

Auth0 присоединяет разрешения роли menu-admin как утверждение к токену доступа, но не к самой роли. Эта информация нужна демонстрационному клиентскому приложению, поскольку оно отображает свой пользовательский интерфейс в зависимости от роли пользователя. Чтобы включить роль пользователя в качестве утверждения в токены, которые Auth0 отправляет клиенту, вы можете использовать правила Auth0.

Когда пользователь успешно входит в ваше приложение, сервер авторизации Auth0 отправляет два токена клиенту:

Маркер доступа

После того, как пользователь успешно аутентифицируется и разрешает доступ, клиентское приложение получает маркер доступа от Auth0. сервер аутентификации. Клиент передает токен доступа в качестве учетных данных всякий раз, когда он вызывает защищенную конечную точку целевого API. Этот токен сообщает серверу, что клиент авторизован для доступа к API.Через утверждение разрешений токен доступа сообщает серверу, какие действия клиент может выполнять с какими ресурсами.

Идентификационный маркер

Идентификационный маркер — это веб-маркер JSON (JWT), содержащий утверждения, представляющие атрибуты профиля пользователя, такие как имя или адрес электронной почты, которые обычно используются клиентами для настройки пользовательского интерфейса.

Используя правила Auth0, вы можете добавить к каждому из этих токенов новое утверждение, представляющее роли, назначенные пользователю.

Что такое правила Auth0?

Правила Auth0 — это функции JavaScript, которые выполняются, когда пользователь входит в ваше приложение.Они запускаются после завершения процесса аутентификации, и вы можете использовать их для настройки и расширения возможностей Auth0. В целях безопасности код правил выполняется в изолированной программной среде, изолированной от кода других клиентов Auth0.

Вы можете легко создавать правила Auth0 с помощью панели инструментов Auth0. Выполните следующие действия, чтобы создать правило, которое добавляет роли пользователей к токенам:

  • Откройте страницу правил на панели инструментов Auth0.

  • Нажмите кнопку Create Rule .

  • Щелкните опцию Пустое правило .

  • Укажите имя для вашего правила, например «Добавить роли пользователей в токены».

  • Затем замените содержимое раздела Script следующей функцией:

  функция (пользователь, контекст, обратный вызов) {
  const namespace = 'https://menu-api.example.com';

  if (context.authorization && context.authorization.roles) {
    const assignRoles = context.authorization.roles;

    if (context.idToken) {
      const idTokenClaims = context.idToken;
      idTokenClaims [`$ {пространство имен} / роли`] = assignRoles;
      context.idToken = idTokenClaims;
    }

    if (context.accessToken) {
      const accessTokenClaims = context.accessToken;
      accessTokenClaims [`$ {пространство имен} / роли`] = assignRoles;
      context.accessToken = accessTokenClaims;
    }
  }

  обратный вызов (ноль, пользователь, контекст);
}  
  • Нажмите кнопку Сохранить изменения .

Что делает это правило?

Когда пользователь успешно аутентифицируется, эта функция правила выполняется, получая три параметра:

  • пользователь : объект, возвращаемый поставщиком удостоверений (например, Auth0 или Google), который представляет вошедшего в систему пользователя.

  • контекст : объект, который хранит контекстную информацию о текущей транзакции аутентификации, такую ​​как IP-адрес или местоположение пользователя.

  • обратный вызов : функция для отправки измененных токенов или ошибки обратно в Auth0.Вы должны вызвать эту функцию, чтобы предотвратить тайм-ауты сценария.

  функция (пользователь, контекст, обратный вызов) {
  
}  

Чтобы ваши пользовательские утверждения не конфликтовали с любыми зарезервированными или внешними утверждениями, вы должны дать им глобально уникальное имя, используя формат пространства имен. По умолчанию Auth0 всегда применяет пространство имен и автоматически исключает из токенов любые пользовательские утверждения с идентификаторами, не связанными с пространством имен.

Пространства имен — это произвольные идентификаторы, поэтому технически вы можете называть свое пространство имен как угодно.Для удобства значение пространства имен — это значение аудитории API, установленное в WHATABYTE Dashboard Demo Settings .

  функция (пользователь, контекст, обратный вызов) {
  const namespace = 'https://menu-api.example.com';

  
}  

Затем вы проверяете, имеет ли объект контекста свойство авторизации и, в свою очередь, имеет ли это свойство свойство ролей :

  функция (пользователь, контекст, обратный вызов) {
  const namespace = 'https: // menu-api.example.com ';

  if (context.authorization && context.authorization.roles) {
   
  }

  
}  

context.authorization — это объект, содержащий информацию, относящуюся к транзакции авторизации, например роли.

context.authorization.roles — это массив строк, содержащий имена ролей, назначенных пользователю.

Затем вы назначаете массив role константе assignRoles и проверяете, присутствует ли токен идентификатора или токен доступа в контексте объекта :

 Функция  (пользователь, контекст, обратный вызов) {
  const namespace = 'https: // menu-api.example.com ';

  if (context.authorization && context.authorization.roles) {
    const assignRoles = context.authorization.roles;

    if (context.idToken) {
      
    }

    if (context.accessToken) {
      
    }
  }

  
}  

Если любой из этих токенов присутствует, вы добавляете к объекту токена свойство / roles с массивом ролей, assignRoles , в качестве его значения, эффективно создавая настраиваемое утверждение для токена, представляющего роли пользователя:

  функция (пользователь, контекст, обратный вызов) {
  const namespace = 'https: // menu-api.example.com ';

  if (context.authorization && context.authorization.roles) {
    const assignRoles = context.authorization.roles;

    if (context.idToken) {
      const idTokenClaims = context.idToken;
      idTokenClaims [`$ {пространство имен} / роли`] = assignRoles;
      context.idToken = idTokenClaims;
    }

    if (context.accessToken) {
      const accessTokenClaims = context.accessToken;
      accessTokenClaims [`$ {пространство имен} / роли`] = assignRoles;
      context.accessToken = accessTokenClaims;
    }
  }

  
}  

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

  функция (пользователь, контекст, обратный вызов) {
  

  обратный вызов (ноль, пользователь, контекст);
}  

Это все, что вам нужно для создания правила Auth0, которое добавляет роли пользователей к токенам.Осталось создать пользователя с ролью menu-admin .

Перед этим проверьте, как пользовательский интерфейс ограничивает доступ к определенным элементам и представлениям пользовательского интерфейса, когда у пользователя нет роли menu-admin .

Вернитесь к демо-клиенту.

Затем щелкните вкладку «Настройки» на левой панели навигации и нажмите кнопку «Изменить» , чтобы изменить настройки демонстрации.

Загрузится вид «Auth0 Demo Settings» .Включите управление доступом на основе ролей (RBAC), чтобы отобразить поле User Role . Заполните это поле следующим значением: menu-admin .

После установки этого значения оставьте все остальные поля как есть. Затем нажмите кнопку Сохранить .

Вернувшись к приложению, войдите в систему . Обратите внимание, что кнопка Добавить элемент больше не отображается на странице «Пункты меню» . Если вы нажмете на пункт меню, вы не увидите кнопок Edit или Delete .

Вам необходимо предоставить себе или любому другому пользователю доступ с правами администратора!

Создайте пользователя с правами администратора

Откройте страницу Users на панели инструментов Auth0 и нажмите Create User . Заполните всплывающую форму следующим образом:

Нажмите кнопку Create . Страница пользователя [email protected] загружается. На этой странице щелкните вкладку «Роли» , а затем нажмите кнопку Назначить роли .

В раскрывающемся списке выберите роль menu-admin , которую вы создали ранее, и нажмите кнопку Assign .Убедитесь, что у пользователя есть разрешения, щелкнув вкладку «Разрешения» . Если это так, ваш администратор настроен и готов к использованию.

В качестве альтернативы вы можете назначить роль menu-admin существующему пользователю, которого вы использовали для доступа к демонстрационному приложению.

Войдите в систему как администратор

Вернитесь в демонстрационный клиент и выйдите из системы.

Нажмите кнопку Sign In еще раз и на этот раз войдите в систему как пример admin @.com или как любой другой пользователь, которому вы предоставили роль menu-admin .

На этот раз пользовательский интерфейс разблокирует функции администратора. Откройте страницу «Меню» и обратите внимание, что кнопка «Добавить элемент», вернулась в верхний правый угол. Щелкните элемент меню и обратите внимание, как теперь вы можете редактировать или удалять элемент.

Однако в этот момент пользователи, не являющиеся администраторами, могут обойти защиту маршрута на стороне клиента, чтобы разблокировать административные функции пользовательского интерфейса. Кроме того, они могут извлекать токен доступа, отправленный Auth0, с помощью инструментов разработчика браузера и, например, делать запросы непосредственно к конечным точкам записи сервера с помощью терминала.

На вашем сервере должен быть реализован ролевой контроль доступа для смягчения этих векторов атак.

Внедрение управления доступом на основе ролей

Для реализации управления доступом на основе ролей (RBAC) в Express вы создаете функцию промежуточного программного обеспечения RBAC, которая проверяет токен доступа, предоставленный в запросе клиента, и проверяет наличие разрешений, требуемых конечной точкой. ему нужен доступ. Вы также должны вызвать эту функцию до того, как ваше приложение достигнет функции обработчика маршрута защищенного контроллера конечной точки.

Следовательно, если в маркере доступа присутствуют надлежащие разрешения, ваша функция промежуточного программного обеспечения RBAC вызывает следующую функцию промежуточного программного обеспечения в цепочке, эффективно предоставляя клиентскому запросу доступ к защищенной конечной точке. В противном случае ваше приложение завершает цикл запроса-ответа и отправляет клиенту ответ с кодом состояния 403 Forbidden .

Чтобы помочь вам легко проверить токен доступа на предмет разрешений, вы будете использовать пакет express-jwt-authz :

  npm install express-jwt-authz  

Используя этот пакет, вы проверите разрешения запрос токена доступа, чтобы определить, есть ли у клиента, отправляющего запрос к защищенной конечной точке, все необходимые разрешения.

Для начала создайте файл для определения функции промежуточного программного обеспечения, которая проверяет разрешения:

  touch src / middleware / permissions.middleware.ts  

Затем заполните src / middleware / permissions.middleware.ts с помощью следующий код:

  const jwtAuthz = require ("express-jwt-authz");

экспорт const checkPermissions = (разрешения: строка | строка []) => {
  return jwtAuthz ([разрешения], {
    customScopeKey: "разрешения",
    checkAllScopes: true,
    failWithError: true
  });
};  

Функция jwtAuthz принимает в качестве первого аргумента массив строк, представляющих разрешения, требуемые конечной точкой.Второй аргумент — это необязательный объект конфигурации. Вы можете настроить поведение jwtAuthz , указав различные параметры следующим образом:

  • customScopeKey : по умолчанию jwtAuthz проверяет разрешения на соответствие области утверждения токена доступа. Вы можете использовать эту опцию, чтобы изменить заявку , которую должен использовать jwtAuthz . В этом случае вы указываете, что токен доступа хранит данные, связанные с разрешениями, в утверждении под названием permissions .

  • checkAllScopes : если установлено значение true , все ожидаемые разрешения конечной точки должны присутствовать в заявлении customScopeKey токена доступа. Если какое-либо разрешение отсутствует, эта функция промежуточного программного обеспечения выдает ошибку, которая фактически запрещает клиентскому приложению, выполняющему запрос, получить доступ к защищенной конечной точке.

  • failWithError : Если установлено значение true , jwtAuthz будет перенаправлять любые ошибки в функцию промежуточного программного обеспечения next () вместо непосредственного завершения ответа.В этом случае jwtAuthz перенаправит ошибку вашей функции промежуточного программного обеспечения errorHandler , где вы можете лучше настроить ответ об ошибке, отправляемый клиенту.

jwtAuthz — это полностью определенная и автономная функция промежуточного программного обеспечения, что означает, что это функция, которая имеет доступ к объекту Request , объекту Response и функции промежуточного программного обеспечения next в цикл запроса-ответа приложения.Таким образом, вы можете технически избежать создания вспомогательной функции checkPermissions и вызывать функцию jwtAuthz непосредственно на каждой конечной точке следующим образом:

  itemsRouter.post (
  "/",
  [
    checkJwt,
    jwtAuthz ([ItemPermissions.CreateItems], {
      customScopeKey: "разрешения",
      checkAllScopes: true,
      failWithError: true
    })
  ],
  async (req: Request, res: Response) => {
    
  }
);

itemsRouter.put (
  "/",
  [
    checkJwt,
    jwtAuthz ([ItemPermissions.UpdateItems], {
      customScopeKey: "разрешения",
      checkAllScopes: true,
      failWithError: true
    })
  ],
  async (req: Request, res: Response) => {
    
  }
);  

Однако для этого потребуется многократно настраивать jwtAuthz на каждой конечной точке. Вместо этого вы используете закрытие JavaScript для создания повторно используемой функциональной оболочки для jwtAuthz . Вспомогательная функция checkPermissions принимает в качестве аргументов необходимые разрешения и создает замыкание вокруг этого значения в своем теле.Затем он возвращает экземпляр jwtAuthz , который может получить доступ к значению разрешений , когда Express его выполняет. Таким образом, вам нужно всего лишь настроить jwtAuthz в одном месте, что сделает ваш код более удобным в обслуживании и менее подверженным ошибкам. Вы примените этот подход к конечным точкам.

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

Определение разрешений локально

Чтобы упростить управление и использование разрешений в коде, вы можете определить их с помощью TypeScript enum .В каталоге src / items создайте следующий файл:

  touch src / items / item-permission.ts  

Заполните src / items / item-permission.ts следующим образом:

  export enum ItemPermission {
  CreateItems = "создать: предметы",
  UpdateItems = "обновление: элементы",
  DeleteItems = "удалить: элементы",
}  

Перечисление TypeScript позволяет вам определять набор именованных констант, которые документируют действия этих констант, а также предотвращают внесение ошибок в ваше приложение путем их опечатки.Каждая константа представляет одно из разрешений, которые вы создали на панели инструментов Auth0.

Применить промежуточное программное обеспечение разрешений

Для защиты конечных точек записи с помощью RBAC необходимо внедрить функцию промежуточного программного обеспечения checkPermissions в определение контроллера и передать ему разрешения, которые требуются конечной точке в качестве аргументов.

Откройте src / items / items.router.ts , найдите раздел Требуемые внешние модули и интерфейсы и добавьте следующий импорт:

 

импорт экспресс, {запрос, ответ} из "экспресс";
импортировать * как ItemService из "./items.service »;
импортировать {BaseItem, Item} из "./item.interface";

импортировать {checkJwt} из "../middleware/authz.middleware";
импортировать {checkPermissions} из "../middleware/permissions.middleware";
импортировать {ItemPermission} из "./item-permission";  

Затем найдите раздел «Определения контроллеров » и обновите следующие определения контроллеров:

 







itemsRouter.use (checkJwt);



itemsRouter.post (
  "/",
  checkPermissions (ItemPermission.CreateItems),
  async (req: Request, res: Response) => {
    пытаться {
      константный элемент: BaseItem = req.body;

      const newItem = ждать ItemService.create (элемент);

      res.status (201) .json (новый элемент);
    } catch (e) {
      res.status (500) .send (e.message);
    }
  }
);



itemsRouter.put (
  "/:я бы",
  checkPermissions (ItemPermission.UpdateItems),
  async (req: Request, res: Response) => {
    идентификатор константы: число = parseInt (req.params.id, 10);

    пытаться {
      const itemUpdate: Item = req.body;

      const existingItem: Item = await ItemService.найти (идентификатор);

      if (existingItem) {
        const updatedItem = ждать ItemService.update (id, itemUpdate);
        вернуть res.status (200) .json (updatedItem);
      }

      const newItem = ждать ItemService.create (itemUpdate);

      res.status (201) .json (новый элемент);
    } catch (e) {
      res.status (500) .send (e.message);
    }
  }
);



itemsRouter.delete (
  "/:я бы",
  checkPermissions (ItemPermission.DeleteItems),
  async (req: Request, res: Response) => {
    пытаться {
      const id: number = parseInt (req.params.id, 10);
      ждать ItemService.remove (id);

      res.sendStatus (204);
    } catch (e) {
      res.status (500) .send (e.message);
    }
  }
);  

Теперь, когда средства защиты авторизации установлены, любая попытка создать новый пункт меню напрямую с использованием токена доступа, не являющегося администратором, приводит к сбою:

  • Функция checkPermissions () , введенная в API-интерфейс POST / menu / items / конечная точка определяет наличие необходимых разрешений.

  • Если требуемые разрешения отсутствуют, он передает исключение 403 вниз по цепочке промежуточного программного обеспечения.

  • Таким образом, вы успешно предотвратите вызов приложения обработчика маршрута этой конечной точки.

Помните, что при установке функции промежуточного программного обеспечения checkJwt () в качестве промежуточного программного обеспечения уровня маршрутизатора вам не нужно включать его на уровне конечной точки. С помощью всего одной строчки кода, itemsRouter.use (checkJwt) , вы защищаете все конечные точки, следующие за ней, от недействительных токенов доступа. Последовательно применяя промежуточное ПО checkPermissions () на уровне контроллера маршрута, вы защищаете этот маршрут от аутентифицированных запросов, которым не хватает необходимого уровня доступа.

Вы эффективно реализуете управление доступом на основе ролей (RBAC), используя двухуровневый подход, основанный на функциях промежуточного программного обеспечения Express.

Выйдите из системы и войдите снова в качестве администратора в демо-клиенте. Попробуйте добавить новый элемент. На странице «Добавить элемент» есть форма, предварительно загруженная с некоторыми данными, чтобы упростить вам этот процесс. Если вы уже создали элемент салата, попробуйте создать элемент кофе со следующими данными:

  имя: Кофе
Стоимость: 299
описание: проснулся
изображение: https: // изображения.ctfassets.net/23aumh6u8s0i/6HS0xLG6bx52KJrqyqfznk/50f9350a7791fa86003024af4762f4ca/whatabyte_coffee-sm.png  

Щелкните этот вновь созданный элемент и обратите внимание, что вы можете отредактировать или удалить его. Попробуйте обе операции.

Упражнение по обеспечению безопасности: удаление роли администратора

Выйдите из демонстрационного приложения.

Щелкните вкладку Settings на левой панели навигации демонстрационного клиента. Затем нажмите кнопку Изменить .

Загрузится страница «Auth0 Demo Settings» .Удалите значение User Role , оставьте поле пустым, затем нажмите кнопку Save .

Теперь либо:

(a) войдите как пользователь без прав администратора, либо

(b) удалите роль menu-admin у вашего текущего пользователя на панели инструментов Auth0 и войдите как этот пользователь.

У вас будет доступ к элементам пользовательского интерфейса администратора. Щелкните по пункту «Чай» и попробуйте его удалить. Вы получите сообщение об ошибке Недостаточная область :

Это сообщение об ошибке сообщает вам, что у вас недостаточно прав для выполнения этого действия.Если вы проверите вкладку «Сеть» или «Консоль» в инструментах разработчика вашего браузера, вы заметите, что ваш сервер Express API ответил с ошибкой 403 (Запрещено) .

Вы получите ошибку того же типа, если попытаетесь добавить или отредактировать элемент. Вы подтвердили, что ваш сервер Express API эффективно защищает ваши конечные точки записи от пользователей, не прошедших проверку подлинности, и от пользователей, прошедших проверку подлинности, у которых нет разрешений на доступ к ним.

Щелкните вкладку Settings на левой панели навигации и нажмите кнопку Modify .Восстановите значение User Role обратно в menu-admin и сохраните изменения. Если вы удалили роль menu-admin у пользователя, вернитесь на панель инструментов Auth0 и верните роль пользователю.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *