@tma.js/sdk 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/dts/launch-params/index.d.ts +1 -0
  2. package/dist/dts/launch-params/retrieveFromUrl.d.ts +6 -0
  3. package/dist/dts/launch-params/types.d.ts +12 -8
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.iife.js +1 -1
  7. package/dist/index.iife.js.map +1 -1
  8. package/dist/index.mjs +243 -238
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +2 -2
  11. package/src/__tests__/globals.ts +39 -0
  12. package/src/back-button/__tests__/BackButton.ts +129 -0
  13. package/src/bridge/__tests__/request.ts +236 -0
  14. package/src/bridge/env/__tests__/hasExternalNotify.ts +15 -0
  15. package/src/bridge/env/__tests__/hasWebviewProxy.ts +15 -0
  16. package/src/bridge/env/__tests__/isIframe.ts +30 -0
  17. package/src/bridge/events/__tests__/createEmitter.ts +143 -0
  18. package/src/bridge/events/__tests__/off.ts +34 -0
  19. package/src/bridge/events/__tests__/on.ts +49 -0
  20. package/src/bridge/events/__tests__/onTelegramEvent.ts +51 -0
  21. package/src/bridge/events/__tests__/once.ts +64 -0
  22. package/src/bridge/events/__tests__/singletonEmitter.ts +22 -0
  23. package/src/bridge/events/__tests__/subscribe.ts +49 -0
  24. package/src/bridge/events/__tests__/unsubscribe.ts +34 -0
  25. package/src/bridge/events/parsers/__tests__/clipboardTextReceived.ts +21 -0
  26. package/src/bridge/events/parsers/__tests__/invoiceClosed.ts +12 -0
  27. package/src/bridge/events/parsers/__tests__/popupClosed.ts +10 -0
  28. package/src/bridge/events/parsers/__tests__/qrTextReceived.ts +9 -0
  29. package/src/bridge/events/parsers/__tests__/theme-changed.ts +42 -0
  30. package/src/bridge/events/parsers/__tests__/viewportChanged.ts +49 -0
  31. package/src/bridge/methods/__tests__/createPostEvent.ts +37 -0
  32. package/src/bridge/methods/__tests__/postEvent.ts +137 -0
  33. package/src/classnames/__tests__/classNames.ts +20 -0
  34. package/src/classnames/__tests__/mergeClassNames.ts +21 -0
  35. package/src/closing-behavior/__tests__/ClosingBehavior.ts +86 -0
  36. package/src/colors/__tests__/isColorDark.ts +12 -0
  37. package/src/colors/__tests__/isRGB.ts +13 -0
  38. package/src/colors/__tests__/isRGBShort.ts +13 -0
  39. package/src/colors/__tests__/toRGB.ts +23 -0
  40. package/src/event-emitter/__tests__/EventEmitter.ts +145 -0
  41. package/src/haptic-feedback/__tests__/HapticFeedback.ts +68 -0
  42. package/src/init/creators/__tests__/createViewport.ts +96 -0
  43. package/src/init-data/__tests__/InitData.ts +98 -0
  44. package/src/init-data/__tests__/chatParser.ts +102 -0
  45. package/src/init-data/__tests__/initDataParser.ts +136 -0
  46. package/src/init-data/__tests__/parseInitData.ts +136 -0
  47. package/src/init-data/__tests__/userParser.ts +96 -0
  48. package/src/launch-params/__tests__/retrieveFromUrl.ts +19 -0
  49. package/src/launch-params/index.ts +1 -0
  50. package/src/launch-params/launchParamsParser.ts +4 -0
  51. package/src/launch-params/retrieveFromLocation.ts +2 -2
  52. package/src/launch-params/retrieveFromPerformance.ts +2 -7
  53. package/src/launch-params/retrieveFromUrl.ts +19 -0
  54. package/src/launch-params/types.ts +13 -8
  55. package/src/logger/__tests__/Logger.ts +107 -0
  56. package/src/main-button/__tests__/MainButton.ts +346 -0
  57. package/src/mini-app/__tests__/MiniApp.ts +140 -0
  58. package/src/misc/__tests__/isRecord.ts +21 -0
  59. package/src/navigation/HashNavigator/__tests__/HashNavigator.ts +144 -0
  60. package/src/navigation/HashNavigator/__tests__/drop.ts +42 -0
  61. package/src/navigation/HashNavigator/__tests__/go.ts +9 -0
  62. package/src/parsing/__tests__/ArrayValueParser.ts +18 -0
  63. package/src/parsing/__tests__/toRecord.ts +10 -0
  64. package/src/parsing/parsers/__tests__/array.ts +39 -0
  65. package/src/parsing/parsers/__tests__/boolean.ts +31 -0
  66. package/src/parsing/parsers/__tests__/date.ts +25 -0
  67. package/src/parsing/parsers/__tests__/json.ts +80 -0
  68. package/src/parsing/parsers/__tests__/number.ts +23 -0
  69. package/src/parsing/parsers/__tests__/rgb.ts +22 -0
  70. package/src/parsing/parsers/__tests__/searchParams.ts +105 -0
  71. package/src/parsing/parsers/__tests__/string.ts +25 -0
  72. package/src/popup/__tests__/Popup.ts +130 -0
  73. package/src/popup/__tests__/preparePopupParams.ts +85 -0
  74. package/src/supports/__tests__/supports.ts +123 -0
  75. package/src/theme-params/__tests__/keys.ts +19 -0
  76. package/src/theme-params/__tests__/parseThemeParams.ts +29 -0
  77. package/src/theme-params/__tests__/serializeThemeParams.ts +29 -0
  78. package/src/theme-params/__tests__/themeParamsParser.ts +29 -0
  79. package/src/timeout/__tests__/isTimeoutError.ts +9 -0
  80. package/src/timeout/__tests__/withTimeout.ts +28 -0
  81. package/src/version/__tests__/compareVersions.ts +19 -0
  82. package/src/viewport/__tests__/isStableViewportPlatform.ts +15 -0
  83. package/src/viewport/__tests__/utils.ts +12 -0
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { ArrayValueParser } from '../ArrayValueParser';
4
+ import { string } from '../parsers';
5
+
6
+ describe('constructor', () => {
7
+ it('should apply parser value directly if it is function', () => {
8
+ const parser = new ArrayValueParser(() => 'Hello!', false);
9
+
10
+ expect(parser.parse(['abc'])).toStrictEqual(['Hello!']);
11
+ });
12
+
13
+ it('should apply parser "parse" method directly if it is ValueParser', () => {
14
+ const parser = new ArrayValueParser(string(), false);
15
+
16
+ expect(parser.parse(['abc'])).toStrictEqual(['abc']);
17
+ });
18
+ });
@@ -0,0 +1,10 @@
1
+ import { expect, it } from 'vitest';
2
+
3
+ import { toRecord } from '../index';
4
+
5
+ it('should throw an error in case, passed value is not JSON object or not JSON object converted to string', () => {
6
+ expect(() => toRecord('')).toThrow();
7
+ expect(() => toRecord(true)).toThrow();
8
+ expect(() => toRecord('{}')).not.toThrow();
9
+ expect(() => toRecord({})).not.toThrow();
10
+ });
@@ -0,0 +1,39 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { array } from '../array';
4
+ import { string } from '../string';
5
+
6
+ it('should return value in case, it is array', () => {
7
+ expect(array().parse(['abc'])).toStrictEqual(['abc']);
8
+ });
9
+
10
+ it('should correctly parse JSON Array presented as string', () => {
11
+ expect(array().parse('["abc"]')).toStrictEqual(['abc']);
12
+ });
13
+
14
+ it('should throw an error in case, passed value is not array', () => {
15
+ expect(() => array().parse(true)).toThrow();
16
+ expect(() => array().parse(1)).toThrow();
17
+ expect(() => array().parse('okay')).toThrow();
18
+ expect(() => array().parse({})).toThrow();
19
+ });
20
+
21
+ describe('of', () => {
22
+ it('should correctly apply item parser to each array item', () => {
23
+ expect(array().of(string()).parse(['abc'])).toStrictEqual(['abc']);
24
+ });
25
+
26
+ it('should throw an error in case, item parser was unable to parse value', () => {
27
+ expect(() => array().of(string()).parse(['abc', {}])).toThrow();
28
+ });
29
+
30
+ it('should use parsing function directly if it is not ValueParser', () => {
31
+ expect(array().of(() => 'Hello!').parse(['abc'])).toStrictEqual(['Hello!']);
32
+ });
33
+ });
34
+
35
+ describe('optional', () => {
36
+ it('should return undefined if value is undefined', () => {
37
+ expect(array().optional().parse(undefined)).toBe(undefined);
38
+ });
39
+ });
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { boolean } from '../boolean';
4
+
5
+ it('should return value in case, it has type boolean', () => {
6
+ expect(boolean().parse(true)).toBe(true);
7
+ expect(boolean().parse(false)).toBe(false);
8
+ });
9
+
10
+ it('should return true in case, value string representation equals "1" or "true"', () => {
11
+ expect(boolean().parse(1)).toBe(true);
12
+ expect(boolean().parse('1')).toBe(true);
13
+ expect(boolean().parse('true')).toBe(true);
14
+ });
15
+
16
+ it('should return false in case, value string representation equals "0" or "false"', () => {
17
+ expect(boolean().parse(0)).toBe(false);
18
+ expect(boolean().parse('0')).toBe(false);
19
+ expect(boolean().parse('false')).toBe(false);
20
+ });
21
+
22
+ it('should throw an error in case, passed value is not of type boolean and its string representation is not "0", "1", "true" or "false"', () => {
23
+ expect(() => boolean().parse('true!')).toThrow();
24
+ expect(() => boolean().parse({})).toThrow();
25
+ });
26
+
27
+ describe('optional', () => {
28
+ it('should return undefined if value is undefined', () => {
29
+ expect(boolean().optional().parse(undefined)).toBe(undefined);
30
+ });
31
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { date } from '../date';
4
+
5
+ it('should return value in case, it is instance of Date', () => {
6
+ const d = new Date();
7
+ expect(date().parse(d)).toBe(d);
8
+ });
9
+
10
+ it('should throw an error in case, passed value cannot be converted to number', () => {
11
+ expect(() => date().parse('true')).toThrow();
12
+ expect(() => date().parse({})).toThrow();
13
+ });
14
+
15
+ it('should create date multiplying value by 1000 in case this value can be converted to number', () => {
16
+ const a = new Date(1000);
17
+ expect(date().parse('1')).toStrictEqual(a);
18
+ expect(date().parse(1)).toStrictEqual(a);
19
+ });
20
+
21
+ describe('optional', () => {
22
+ it('should return undefined if value is undefined', () => {
23
+ expect(date().optional().parse(undefined)).toBe(undefined);
24
+ });
25
+ });
@@ -0,0 +1,80 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { boolean } from '../boolean';
4
+ import { json } from '../json';
5
+ import { number } from '../number';
6
+ import { string } from '../string';
7
+
8
+ it('should throw an error in case, passed value is not JSON object or not JSON object converted to string', () => {
9
+ const parser = json({});
10
+ expect(() => parser.parse('')).toThrow();
11
+ expect(() => parser.parse(true)).toThrow();
12
+ expect(() => parser.parse('{}')).not.toThrow();
13
+ expect(() => parser.parse({})).not.toThrow();
14
+ });
15
+
16
+ it('should throw an error in case, passed value does not contain required field presented in schema', () => {
17
+ const parser = json({ prop: string() });
18
+ expect(() => parser.parse({})).toThrow();
19
+ });
20
+
21
+ it('should ignore field in case its value is undefined', () => {
22
+ const parser = json<{ prop?: string }>({ prop: undefined });
23
+ expect(parser.parse({})).toStrictEqual({});
24
+ });
25
+
26
+ describe('field definition as object', () => {
27
+ it('should extract field value from the specified property "from"', () => {
28
+ const parser = json({
29
+ a: {
30
+ type: (value) => value,
31
+ from: 'b',
32
+ },
33
+ });
34
+ expect(parser.parse({ b: 'Hello there!' })).toStrictEqual({ a: 'Hello there!' });
35
+ });
36
+
37
+ it('should extract field value from schema field name, if "from" was not specified', () => {
38
+ const parser = json({
39
+ a: {
40
+ type: (value) => value,
41
+ },
42
+ });
43
+ expect(parser.parse({ a: 'Hello there!' })).toStrictEqual({ a: 'Hello there!' });
44
+ });
45
+
46
+ it('should apply parser passed as ValueParser', () => {
47
+ const parser = json({
48
+ a: {
49
+ type: string(),
50
+ },
51
+ });
52
+ expect(parser.parse({ a: 'Hello there!' })).toStrictEqual({ a: 'Hello there!' });
53
+ });
54
+ });
55
+
56
+ it('should also apply parser presented as function', () => {
57
+ const parser = json({
58
+ prop: () => 'static value',
59
+ });
60
+ expect(parser.parse({ prop: 999 })).toStrictEqual({ prop: 'static value' });
61
+ });
62
+
63
+ it('should throw an error in case, passed value contains field of different type presented in schema', () => {
64
+ const parser = json({ prop: string() });
65
+ expect(() => parser.parse({ prop: {} })).toThrow();
66
+ });
67
+
68
+ it('should correctly parse built-in types', () => {
69
+ const parser = json({
70
+ bool: boolean(),
71
+ string: string(),
72
+ number: number(),
73
+ });
74
+ const obj = {
75
+ bool: true,
76
+ string: '123',
77
+ number: 999,
78
+ };
79
+ expect(parser.parse(obj)).toStrictEqual(obj);
80
+ });
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { number } from '../number';
4
+
5
+ it('should return value in case, it has type number', () => {
6
+ expect(number().parse(9992)).toBe(9992);
7
+ });
8
+
9
+ it('should return value converted to number in case, it is number converted to string', () => {
10
+ expect(number().parse('9992')).toBe(9992);
11
+ });
12
+
13
+ it('should throw an error in case, passed value is not of type number or does not represent number converted to string', () => {
14
+ expect(() => number().parse(true)).toThrow();
15
+ expect(() => number().parse('vvv')).toThrow();
16
+ expect(() => number().parse({})).toThrow();
17
+ });
18
+
19
+ describe('optional', () => {
20
+ it('should return undefined if value is undefined', () => {
21
+ expect(number().optional().parse(undefined)).toBe(undefined);
22
+ });
23
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { rgb } from '../rgb';
4
+
5
+ it('should return value in case, it represents RGB color', () => {
6
+ expect(rgb().parse('#fff')).toBe('#ffffff');
7
+ });
8
+
9
+ it('should throw an error in case, passed value is not of type string', () => {
10
+ expect(() => rgb().parse(true)).toThrow();
11
+ expect(() => rgb().parse({})).toThrow();
12
+ });
13
+
14
+ it('should throw an error in case, passed value does not represent RGB string', () => {
15
+ expect(() => rgb().parse('my custom string')).toThrow();
16
+ });
17
+
18
+ describe('optional', () => {
19
+ it('should return undefined if value is undefined', () => {
20
+ expect(rgb().optional().parse(undefined)).toBe(undefined);
21
+ });
22
+ });
@@ -0,0 +1,105 @@
1
+ import { expect, it } from 'vitest';
2
+
3
+ import { date } from '../date';
4
+ import { searchParams } from '../searchParams';
5
+ import { string } from '../string';
6
+
7
+ it('should throw an error in case, passed value is not of type string or URLSearchParams', () => {
8
+ const parser = searchParams({});
9
+ expect(() => parser.parse(true)).toThrow();
10
+ expect(() => parser.parse({})).toThrow();
11
+ expect(() => parser.parse('true')).not.toThrow();
12
+ expect(() => parser.parse(new URLSearchParams())).not.toThrow();
13
+ });
14
+
15
+ it('should throw an error in case, passed value does not contain required field presented in schema', () => {
16
+ const parser = searchParams({ prop: string() });
17
+
18
+ try {
19
+ parser.parse('abc=123');
20
+ } catch (e) {
21
+ expect(e).toMatchObject({
22
+ message: 'Unable to parse value',
23
+ cause: {
24
+ message: 'Unable to parse field "prop" as string',
25
+ cause: {
26
+ message: 'Unable to parse value as string',
27
+ cause: {
28
+ message: 'Value has unexpected type',
29
+ },
30
+ },
31
+ },
32
+ });
33
+ }
34
+ expect.assertions(1);
35
+ });
36
+
37
+ it('should not throw an error in case, passed value does not contain optional field presented in schema', () => {
38
+ const parser = searchParams<{ prop?: string }>({
39
+ prop: string().optional(),
40
+ });
41
+ expect(parser.parse('')).toEqual({});
42
+ expect(parser.parse('prop=abc')).toEqual({ prop: 'abc' });
43
+ });
44
+
45
+ it('should use parser with unspecified type', () => {
46
+ const parser = searchParams<{ prop: unknown }>({
47
+ prop: () => {
48
+ throw new Error('Just an error');
49
+ },
50
+ });
51
+
52
+ try {
53
+ parser.parse('prop=');
54
+ } catch (e) {
55
+ expect(e).toMatchObject({
56
+ message: 'Unable to parse value',
57
+ cause: {
58
+ message: 'Unable to parse field "prop"',
59
+ cause: {
60
+ message: 'Just an error',
61
+ },
62
+ },
63
+ });
64
+ }
65
+ expect.assertions(1);
66
+ });
67
+
68
+ it('should throw an error in case, passed value contains field of different type presented in schema', () => {
69
+ const parser = searchParams({ prop: date() });
70
+
71
+ try {
72
+ parser.parse('prop=abc');
73
+ } catch (e) {
74
+ expect(e).toMatchObject({
75
+ message: 'Unable to parse value',
76
+ cause: {
77
+ message: 'Unable to parse field "prop" as Date',
78
+ cause: {
79
+ message: 'Unable to parse value as Date',
80
+ cause: {
81
+ message: 'Unable to parse value as number',
82
+ cause: {
83
+ message: 'Value has unexpected type',
84
+ },
85
+ },
86
+ },
87
+ },
88
+ });
89
+ }
90
+ expect.assertions(1);
91
+ });
92
+
93
+ it('should correctly parse built-in types', () => {
94
+ const parser = searchParams({
95
+ date: date(),
96
+ string: string(),
97
+ });
98
+ const params = new URLSearchParams();
99
+ params.set('date', '66653332');
100
+ params.set('string', 'some string');
101
+ expect(parser.parse(params)).toEqual({
102
+ date: new Date(66653332000),
103
+ string: 'some string',
104
+ });
105
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { string } from '../string';
4
+
5
+ it('should return value in case, it has type string', () => {
6
+ expect(string().parse('abc')).toBe('abc');
7
+ });
8
+
9
+ it('should convert value to string in case, it has type number', () => {
10
+ expect(string().parse(1)).toBe('1');
11
+ });
12
+
13
+ it('should throw an error in case, passed value is not string or number', () => {
14
+ expect(() => string().parse({})).toThrow();
15
+ expect(() => string().parse([])).toThrow();
16
+ expect(() => string().parse(false)).toThrow();
17
+ expect(() => string().parse(null)).toThrow();
18
+ expect(() => string().parse(undefined)).toThrow();
19
+ });
20
+
21
+ describe('optional', () => {
22
+ it('should return undefined if value is undefined', () => {
23
+ expect(string().optional().parse(undefined)).toBe(undefined);
24
+ });
25
+ });
@@ -0,0 +1,130 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ // import {emitDesktopEvent, mockDesktop} from '../../../tests';
4
+ // import { Popup } from './Popup';
5
+ // import {Bridge} from '@tma.js/bridge';
6
+ // import {PopupParams} from './types';
7
+ // import {preparePopupParams} from './utils';
8
+
9
+ // beforeAll(mockDesktop);
10
+
11
+ describe('components', () => {
12
+ describe('Popup', () => {
13
+ it('should be fine', () => {
14
+ expect(true).toBe(true);
15
+ });
16
+ // it('isOpened', () => {
17
+ // it('should emit event "openChange" with specified value in setter', () => {
18
+ // const popup = new Popup('7');
19
+ // const spy = vi.spyOn((popup as any).ee, 'emit');
20
+ // (popup as any).isOpened = true;
21
+ // expect(spy).lastCalledWith('openChange', true);
22
+ //
23
+ // (popup as any).isOpened = false;
24
+ // expect(spy).lastCalledWith('openChange', false);
25
+ // });
26
+ // });
27
+ //
28
+ // it('show', () => {
29
+ // it('should throw an error in case, current version is less than 6.2', () => {
30
+ // expect(() => new Popup('6.1').show({message: 'Hey!'})).toThrow();
31
+ // expect(() => new Popup('6.2').show({message: 'Hey!'})).not.toThrow();
32
+ // });
33
+ //
34
+ // it('should call bridge event "web_app_open_popup" with prepared parameters', () => {
35
+ // const bridge = new Bridge();
36
+ // const spy = vi.spyOn(bridge, 'postEvent');
37
+ // const popup = new Popup('7', {bridge});
38
+ // const params: PopupParams = {message: 'Message'};
39
+ // const prepared = preparePopupParams(params);
40
+ // popup.show(params);
41
+ // expect(spy).toHaveBeenCalledWith('web_app_open_popup', prepared);
42
+ // });
43
+ //
44
+ // it('should emit event "open" with prepared params', () => {
45
+ // const popup = new Popup('7');
46
+ // const spy = vi.spyOn((popup as any).ee, 'emit');
47
+ // const params: PopupParams = {message: 'Message'};
48
+ // const prepared = preparePopupParams(params);
49
+ // popup.show(params);
50
+ // expect(spy).toHaveBeenCalledWith('open', prepared);
51
+ // });
52
+ //
53
+ // it('should set "isOpened" property to true', () => {
54
+ // const popup = new Popup('7');
55
+ // expect(popup.isOpened).toBe(false);
56
+ // popup.show({message: 'Message'});
57
+ // expect(popup.isOpened).toBe(true);
58
+ // });
59
+ //
60
+ // it('should set "isOpened" property to false when promise is resolved', async () => {
61
+ // const popup = new Popup('7');
62
+ // const promise = popup.show({message: 'Message'});
63
+ //
64
+ // emitDesktopEvent('popup_closed', {button_id: null});
65
+ // await promise;
66
+ // expect(popup.isOpened).toBe(false);
67
+ // });
68
+ //
69
+ // it('should set "isOpened" property to true', () => {
70
+ // const popup = new Popup('7');
71
+ // popup.show({message: 'Message'});
72
+ // expect(popup.isOpened).toBe(true);
73
+ // });
74
+ //
75
+ // it('should emit close event with specified button_id when promise is resolved',
76
+ // async () => {
77
+ // const popup = new Popup('7');
78
+ // const spy = vi.spyOn((popup as any).ee, 'emit');
79
+ // const promise = popup.show({message: 'Message'});
80
+ // emitDesktopEvent('popup_closed', {button_id: 'Hey!'});
81
+ // await promise;
82
+ // expect(spy).lastCalledWith('close', 'Hey!');
83
+ // });
84
+ // });
85
+ //
86
+ // it('showAlert', () => {
87
+ // it('should call "show" with passed message and buttons = [{type: "close"}]', () => {
88
+ // const popup = new Popup('7');
89
+ // const spy = vi.spyOn(popup, 'show');
90
+ //
91
+ // popup.showAlert('Message');
92
+ //
93
+ // expect(spy).toHaveBeenCalledWith({
94
+ // message: 'Message',
95
+ // buttons: [{type: 'close'}],
96
+ // });
97
+ // });
98
+ // });
99
+ //
100
+ // it('showConfirm', () => {
101
+ // test(
102
+ // 'should call "show" with passed message and ' +
103
+ // 'buttons = [{type: "ok", id: "ok"}, {id: "cancel", type: "cancel"}]',
104
+ // () => {
105
+ // const popup = new Popup('7');
106
+ // const spy = vi.spyOn(popup, 'show');
107
+ //
108
+ // popup.showConfirm('Message');
109
+ //
110
+ // expect(spy).toHaveBeenCalledWith({
111
+ // message: 'Message',
112
+ // buttons: [{type: 'ok', id: 'ok'}, {id: 'cancel', type: 'cancel'}],
113
+ // });
114
+ // },
115
+ // );
116
+ //
117
+ // it('should resolve true in case, user pressed button with id "ok"', async () => {
118
+ // const promise = new Popup('7').showConfirm('Message');
119
+ // emitDesktopEvent('popup_closed', {button_id: 'ok'});
120
+ // expect(await promise).toBe(true);
121
+ // });
122
+ //
123
+ // it('should resolve false in case, user pressed any other button', async () => {
124
+ // const promise = new Popup('7').showConfirm('Message');
125
+ // emitDesktopEvent('popup_closed', {button_id: 'cancel'});
126
+ // await expect(promise).resolves.toBe(false);
127
+ // });
128
+ // });
129
+ });
130
+ });
@@ -0,0 +1,85 @@
1
+ import { expect, it } from 'vitest';
2
+
3
+ import { preparePopupParams } from '../preparePopupParams';
4
+
5
+ /**
6
+ * Creates test text.
7
+ * @param length - text length.
8
+ */
9
+ function createText(length: number): string {
10
+ return new Array(length).fill('a').join('');
11
+ }
12
+
13
+ it('should throw an error in case, title length is more than 64 symbols', () => {
14
+ expect(() => preparePopupParams({
15
+ title: createText(65),
16
+ message: 'Hey!',
17
+ })).toThrow(/^Title has incorrect size/);
18
+
19
+ expect(() => preparePopupParams({
20
+ title: createText(64),
21
+ message: 'Hey!',
22
+ })).not.toThrow();
23
+ });
24
+
25
+ it('should throw an error in case, message length is zero or more than 256 symbols', () => {
26
+ expect(() => preparePopupParams({
27
+ message: '',
28
+ })).toThrow(/^Message has incorrect size/);
29
+
30
+ expect(() => preparePopupParams({
31
+ message: createText(257),
32
+ })).toThrow(/^Message has incorrect size/);
33
+
34
+ expect(() => preparePopupParams({
35
+ message: createText(256),
36
+ })).not.toThrow();
37
+ });
38
+
39
+ it('should throw an error in case, buttons count is more than 3', () => {
40
+ expect(() => preparePopupParams({
41
+ message: 'a',
42
+ buttons: new Array(4).fill({ type: 'close' }),
43
+ })).toThrow(/^Buttons have incorrect size/);
44
+
45
+ expect(() => preparePopupParams({
46
+ message: 'a',
47
+ buttons: new Array(3).fill({ type: 'close' }),
48
+ })).not.toThrow();
49
+ });
50
+
51
+ it('should append button type "close" in case, buttons array is empty', () => {
52
+ expect(preparePopupParams({ message: 'a' }).buttons).toStrictEqual([{
53
+ type: 'close',
54
+ id: '',
55
+ }]);
56
+ });
57
+
58
+ it('should throw an error in case, some button text length size is zero or more than 64 symbols', () => {
59
+ expect(() => preparePopupParams({
60
+ message: 'A',
61
+ buttons: [{ type: 'default', text: createText(65) }],
62
+ })).toThrowError(/^Button text with type/);
63
+
64
+ expect(() => preparePopupParams({
65
+ message: 'A',
66
+ buttons: [{ type: 'default', text: '' }],
67
+ })).toThrowError(/^Button text with type/);
68
+
69
+ expect(() => preparePopupParams({
70
+ message: 'A',
71
+ buttons: [{ type: 'default', text: createText(64) }],
72
+ })).not.toThrow();
73
+ });
74
+
75
+ it('should fulfill all optional popup parameters', () => {
76
+ expect(preparePopupParams({
77
+ message: 'Message',
78
+ buttons: [{ type: 'default', text: 'Wow!' }, { type: 'close' }],
79
+ }))
80
+ .toStrictEqual({
81
+ title: '',
82
+ message: 'Message',
83
+ buttons: [{ id: '', type: 'default', text: 'Wow!' }, { type: 'close', id: '' }],
84
+ });
85
+ });