@muonic/muon 0.0.2-beta.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.
- package/.nycrc +17 -0
- package/.versionrc +3 -0
- package/CHANGELOG.md +389 -0
- package/components/card/index.js +1 -0
- package/components/card/src/card-component.js +43 -0
- package/components/card/src/card-styles.css +25 -0
- package/components/card/src/config-tokens.json +11 -0
- package/components/card/src/design-tokens.json +34 -0
- package/components/card/story.js +52 -0
- package/components/cta/index.js +1 -0
- package/components/cta/src/config-tokens.json +11 -0
- package/components/cta/src/cta-component.js +174 -0
- package/components/cta/src/cta-styles.css +105 -0
- package/components/cta/src/design-tokens.json +132 -0
- package/components/cta/story.js +99 -0
- package/components/detail/index.js +1 -0
- package/components/detail/src/config-tokens.json +11 -0
- package/components/detail/src/design-tokens.json +102 -0
- package/components/detail/src/detail-component.js +27 -0
- package/components/detail/src/detail-styles.css +83 -0
- package/components/detail/story.js +33 -0
- package/components/form/index.js +1 -0
- package/components/form/src/config-tokens.json +11 -0
- package/components/form/src/design-tokens.json +9 -0
- package/components/form/src/form-component.js +197 -0
- package/components/form/src/form-styles.css +10 -0
- package/components/form/story.js +71 -0
- package/components/icon/index.js +1 -0
- package/components/icon/src/config-tokens.json +31 -0
- package/components/icon/src/design-tokens.json +8 -0
- package/components/icon/src/icon-component.js +91 -0
- package/components/icon/src/icon-styles.css +26 -0
- package/components/icon/story.js +26 -0
- package/components/image/index.js +1 -0
- package/components/image/src/config-tokens.json +26 -0
- package/components/image/src/image-component.js +96 -0
- package/components/image/src/image-styles.css +71 -0
- package/components/image/story.js +31 -0
- package/components/inputter/index.js +1 -0
- package/components/inputter/src/config-tokens.json +14 -0
- package/components/inputter/src/design-tokens.json +308 -0
- package/components/inputter/src/inputter-component.js +227 -0
- package/components/inputter/src/inputter-styles-detail.css +59 -0
- package/components/inputter/src/inputter-styles.css +305 -0
- package/components/inputter/src/inputter-styles.slotted.css +64 -0
- package/components/inputter/story.js +243 -0
- package/css/accessibility.css +3 -0
- package/css/default.css +9 -0
- package/css/global.css +8 -0
- package/directives/image-loader-directive.js +116 -0
- package/directives/svg-loader-directive.js +94 -0
- package/index.js +52 -0
- package/mixins/card-mixin.js +27 -0
- package/mixins/detail-mixin.js +128 -0
- package/mixins/form-associate-mixin.js +36 -0
- package/mixins/form-element-mixin.js +378 -0
- package/mixins/image-holder-mixin.js +20 -0
- package/mixins/mask-mixin.js +159 -0
- package/mixins/validation-mixin.js +272 -0
- package/muon-element/index.js +97 -0
- package/package.json +72 -0
- package/rollup.config.mjs +30 -0
- package/scripts/build/storybook/index.mjs +11 -0
- package/scripts/build/storybook/run.mjs +47 -0
- package/scripts/rollup-plugins.mjs +116 -0
- package/scripts/serve/index.mjs +11 -0
- package/scripts/serve/run.mjs +27 -0
- package/scripts/style-dictionary.mjs +64 -0
- package/scripts/utils/config.mjs +30 -0
- package/scripts/utils/index.mjs +283 -0
- package/storybook/find-stories.js +36 -0
- package/storybook/server.config.mjs +19 -0
- package/storybook/stories.js +86 -0
- package/storybook/tokens/color.js +87 -0
- package/storybook/tokens/font.js +52 -0
- package/storybook/tokens/spacer.js +48 -0
- package/tests/README.md +3 -0
- package/tests/components/card/__snapshots__/card.test.snap.js +70 -0
- package/tests/components/card/card.test.js +81 -0
- package/tests/components/cta/__snapshots__/cta.test.snap.js +246 -0
- package/tests/components/cta/cta.test.js +212 -0
- package/tests/components/form/__snapshots__/form.test.snap.js +115 -0
- package/tests/components/form/form.test.js +336 -0
- package/tests/components/icon/__snapshots__/icon.test.snap.js +95 -0
- package/tests/components/icon/icon.test.js +197 -0
- package/tests/components/image/__snapshots__/image.test.snap.js +205 -0
- package/tests/components/image/image.test.js +314 -0
- package/tests/components/image/images/15.png +0 -0
- package/tests/components/image/images/150.png +0 -0
- package/tests/components/inputter/__snapshots__/inputter.test.snap.js +357 -0
- package/tests/components/inputter/inputter.test.js +427 -0
- package/tests/helpers/index.js +30 -0
- package/tests/mixins/__snapshots__/card.test.snap.js +35 -0
- package/tests/mixins/__snapshots__/detail.test.snap.js +237 -0
- package/tests/mixins/__snapshots__/form-element.test.snap.js +137 -0
- package/tests/mixins/__snapshots__/mask.test.snap.js +53 -0
- package/tests/mixins/__snapshots__/validation.test.snap.js +297 -0
- package/tests/mixins/card.test.js +63 -0
- package/tests/mixins/detail.test.js +223 -0
- package/tests/mixins/form-element.test.js +473 -0
- package/tests/mixins/mask.test.js +261 -0
- package/tests/mixins/muon-element.test.js +52 -0
- package/tests/mixins/validation.test.js +423 -0
- package/tests/runner/commands.mjs +19 -0
- package/tests/scripts/utils/card-component.js +26 -0
- package/tests/scripts/utils/muon.config.test.json +13 -0
- package/tests/scripts/utils/single.component.config.json +5 -0
- package/tests/scripts/utils/test-runner.mjs +1 -0
- package/tests/scripts/utils/utils-test.mjs +284 -0
- package/tests/utils/validation.functions.test.js +199 -0
- package/tokens/theme/color.json +482 -0
- package/tokens/theme/font.json +61 -0
- package/tokens/theme/size.json +27 -0
- package/tokens/theme/spacer.json +73 -0
- package/tokens/utils/formats/reference.js +17 -0
- package/tokens/utils/modular-scale.js +33 -0
- package/tokens/utils/templates/font-face.css.template +30 -0
- package/tokens/utils/transforms/color.js +27 -0
- package/tokens/utils/transforms/string.js +6 -0
- package/tokens/utils/validation.json +76 -0
- package/utils/scroll/index.js +31 -0
- package/utils/validation/index.js +205 -0
- package/web-test-runner.browserstack.config.mjs +123 -0
- package/web-test-runner.config.mjs +44 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<% _.forIn(properties && properties.asset && properties.asset.font, function(font) {
|
|
2
|
+
var fileFormatArr = [];
|
|
3
|
+
if (font.eot) {
|
|
4
|
+
fileFormatArr.push("url('" + font.eot.value + "');\n\tsrc: url('" + font.eot.value + "?#iefix') format('embedded-opentype')");
|
|
5
|
+
}
|
|
6
|
+
if (font.otf) {
|
|
7
|
+
fileFormatArr.push("url('" + font.otf.value + "') format('otf')");
|
|
8
|
+
}
|
|
9
|
+
if (font.ttf) {
|
|
10
|
+
fileFormatArr.push("url('" + font.ttf.value + "') format('truetype')");
|
|
11
|
+
}
|
|
12
|
+
if (font.svg) {
|
|
13
|
+
fileFormatArr.push("url('" + font.svg.value + "#" + font.name.value.replace(/ /g,'%20') + "') format('svg')");
|
|
14
|
+
}
|
|
15
|
+
if (font.woff) {
|
|
16
|
+
fileFormatArr.push("url('" + font.woff.value + "') format('woff')");
|
|
17
|
+
}
|
|
18
|
+
if (font.woff2) {
|
|
19
|
+
fileFormatArr.push("url('" + font.woff2.value + "') format('woff2')");
|
|
20
|
+
}
|
|
21
|
+
%>
|
|
22
|
+
@font-face {
|
|
23
|
+
font-family: "<%= font.name.value %>";
|
|
24
|
+
font-display: fallback;<% if (font.unicodeRange) { %>
|
|
25
|
+
unicode-range: <%= font.unicodeRange.value %>;<% } %>
|
|
26
|
+
src: <%= fileFormatArr.join(',\n\t\t') %>;<% if (font.style) { %>
|
|
27
|
+
font-style: <%= font.style.value %>;<% } if (font.weight) { %>
|
|
28
|
+
font-weight: <%= font.weight.value %>;<% } %>
|
|
29
|
+
}
|
|
30
|
+
<% }); %>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const chroma = require('chroma-js');
|
|
2
|
+
|
|
3
|
+
const colorTransform = (token) => {
|
|
4
|
+
const { value, modify = [] } = token;
|
|
5
|
+
let color = chroma(value);
|
|
6
|
+
// iterate over the modify array (see tokens/color.json)
|
|
7
|
+
// and apply each modification in order
|
|
8
|
+
modify.forEach(({ type, amount }) => {
|
|
9
|
+
// modifier type must match a method name in chromajs
|
|
10
|
+
// https://gka.github.io/chroma.js/
|
|
11
|
+
// chroma methods can be chained, so each time we override the color variable
|
|
12
|
+
// we can still call other chroma methods, similar to
|
|
13
|
+
// chroma(value).brighten(1).darken(1).hex();
|
|
14
|
+
color = color[type](amount);
|
|
15
|
+
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return color.hex();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
name: 'color/css',
|
|
23
|
+
type: 'value',
|
|
24
|
+
transitive: true,
|
|
25
|
+
matcher: (token) => token.modify,
|
|
26
|
+
transformer: colorTransform
|
|
27
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"validation": {
|
|
3
|
+
"isRequired": {
|
|
4
|
+
"message": {
|
|
5
|
+
"description": "Display message for isRequired validation function",
|
|
6
|
+
"value": "This field is required"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"isNumber": {
|
|
10
|
+
"message": {
|
|
11
|
+
"description": "Display message for isNumber validation function",
|
|
12
|
+
"value": "Needs to be a number"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"isInteger": {
|
|
16
|
+
"message": {
|
|
17
|
+
"description": "Display message for isInteger validation function",
|
|
18
|
+
"value": "Needs to be a whole number"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"isEmail": {
|
|
22
|
+
"message": {
|
|
23
|
+
"description": "Display message for isEmail validation function",
|
|
24
|
+
"value": "Your email does not look right"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"minLength": {
|
|
28
|
+
"message": {
|
|
29
|
+
"description": "Display message for minLength validation function",
|
|
30
|
+
"value": "Length must be at least $min characters"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"maxLength": {
|
|
34
|
+
"message": {
|
|
35
|
+
"description": "Display message for maxLength validation function",
|
|
36
|
+
"value": "Length must be no longer than $max characters"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"isBetween": {
|
|
40
|
+
"message": {
|
|
41
|
+
"description": "Display message for isBetween validation function",
|
|
42
|
+
"value": "Length must be between $min and $max characters"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"isDate": {
|
|
46
|
+
"message": {
|
|
47
|
+
"description": "Display message for isDate validation function",
|
|
48
|
+
"value": "Your date does not look right"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"minDate": {
|
|
52
|
+
"message": {
|
|
53
|
+
"description": "Display message for minDate validation function",
|
|
54
|
+
"value": "Date must be on or after $minDate"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"maxDate": {
|
|
58
|
+
"message": {
|
|
59
|
+
"description": "Display message for maxDate validation function",
|
|
60
|
+
"value": "Date must be on or before $maxDate"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"hasNumbers": {
|
|
64
|
+
"message": {
|
|
65
|
+
"description": "Display message for hasNumbers validation function",
|
|
66
|
+
"value": "Must include at least one number"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"hasLetters": {
|
|
70
|
+
"message": {
|
|
71
|
+
"description": "Display message for hasLetters validation function",
|
|
72
|
+
"value": "Must include at least one letter"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export default ({
|
|
2
|
+
element, // the element to scroll to
|
|
3
|
+
focusOn = element // optional element that gets focus
|
|
4
|
+
} = {}) => {
|
|
5
|
+
const motionQuery = window.matchMedia('(prefers-reduced-motion)');
|
|
6
|
+
|
|
7
|
+
setTimeout(function () { // Firefox needs this in order to allow the event queue to clear before scrolling
|
|
8
|
+
if (!motionQuery.matches) {
|
|
9
|
+
element.scrollIntoView({
|
|
10
|
+
behavior: 'smooth'
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}, 0);
|
|
14
|
+
|
|
15
|
+
focusOn.focus({
|
|
16
|
+
preventScroll: !motionQuery.matches
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// https://css-tricks.com/smooth-scrolling-accessibility/
|
|
20
|
+
// "In order for this to work on non-focusable target elements (section, div, span, h1-6, ect),
|
|
21
|
+
// we have to set tabindex="-1" on them"
|
|
22
|
+
|
|
23
|
+
if (focusOn !== document.activeElement) { // Checking if the target was focused
|
|
24
|
+
const tabIndex = focusOn.getAttribute('tabindex');
|
|
25
|
+
focusOn.setAttribute('tabindex', '-1'); // Adding tabindex for elements not focusable
|
|
26
|
+
focusOn.focus({
|
|
27
|
+
preventScroll: !motionQuery.matches
|
|
28
|
+
}); // Setting focus
|
|
29
|
+
focusOn.setAttribute('tabindex', tabIndex); //resetting tabindex
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VALIDATION_IS_REQUIRED_MESSAGE,
|
|
3
|
+
VALIDATION_IS_NUMBER_MESSAGE,
|
|
4
|
+
VALIDATION_IS_INTEGER_MESSAGE,
|
|
5
|
+
VALIDATION_IS_EMAIL_MESSAGE,
|
|
6
|
+
VALIDATION_MIN_LENGTH_MESSAGE,
|
|
7
|
+
VALIDATION_MAX_LENGTH_MESSAGE,
|
|
8
|
+
VALIDATION_IS_BETWEEN_MESSAGE,
|
|
9
|
+
VALIDATION_IS_DATE_MESSAGE,
|
|
10
|
+
VALIDATION_MIN_DATE_MESSAGE,
|
|
11
|
+
VALIDATION_MAX_DATE_MESSAGE,
|
|
12
|
+
VALIDATION_HAS_NUMBERS_MESSAGE,
|
|
13
|
+
VALIDATION_HAS_LETTERS_MESSAGE
|
|
14
|
+
} from '@muon/tokens';
|
|
15
|
+
|
|
16
|
+
const regularExpressions = {
|
|
17
|
+
// eslint-disable-next-line no-useless-escape
|
|
18
|
+
email: /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const withoutChar = (value, separator) => {
|
|
22
|
+
return value.split(separator).join('');
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const convertIsoDate = (isoDate) => {
|
|
26
|
+
return isoDate.split('-').reverse().join('/');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const isRequired = (inputter, value) => {
|
|
30
|
+
return (value === undefined || value.length === 0) && VALIDATION_IS_REQUIRED_MESSAGE;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const isNumber = (inputter, value) => {
|
|
34
|
+
const number = inputter.separator ? withoutChar(value, inputter.separator) : value;
|
|
35
|
+
const val = Number(number);
|
|
36
|
+
const isNum = typeof val === 'number' && !isNaN(val);
|
|
37
|
+
return value.length > 0 && !isNum && VALIDATION_IS_NUMBER_MESSAGE;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const isInteger = (inputter, value) => {
|
|
41
|
+
const number = inputter.separator ? withoutChar(value, inputter.separator) : value;
|
|
42
|
+
const val = Number(number);
|
|
43
|
+
const isInt = typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
|
|
44
|
+
|
|
45
|
+
return value.length > 0 && !isInt && VALIDATION_IS_INTEGER_MESSAGE;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const isEmail = (inputter, value) => {
|
|
49
|
+
const emailRegexp = new RegExp(regularExpressions.email, 'i');
|
|
50
|
+
return value.length > 0 && !emailRegexp.test(value) && VALIDATION_IS_EMAIL_MESSAGE;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const minLength = (inputter, value, min) => {
|
|
54
|
+
const str = inputter.separator ? withoutChar(value, inputter.separator) : value;
|
|
55
|
+
return value.length > 0 && str.length < min && VALIDATION_MIN_LENGTH_MESSAGE.replace('$min', min);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const maxLength = (inputter, value, max) => {
|
|
59
|
+
const str = inputter.separator ? withoutChar(value, inputter.separator) : value;
|
|
60
|
+
return value.length > 0 && str.length > max && VALIDATION_MAX_LENGTH_MESSAGE.replace('$max', max);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const isBetween = (inputter, value, min, max) => {
|
|
64
|
+
const str = inputter.separator ? withoutChar(value, inputter.separator) : value;
|
|
65
|
+
return value.length > 0 && (str.length < min || str.length > max) && VALIDATION_IS_BETWEEN_MESSAGE.replace('$min', min).replace('$max', max);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const stringToDate = (dateString) => {
|
|
69
|
+
const arr = dateString.indexOf('/') !== -1 ? dateString.split('/') : dateString.split('-');
|
|
70
|
+
|
|
71
|
+
let dayString;
|
|
72
|
+
let monthString;
|
|
73
|
+
let yearString;
|
|
74
|
+
|
|
75
|
+
if (dateString.indexOf('/') !== -1) {
|
|
76
|
+
dayString = arr[0];
|
|
77
|
+
monthString = arr[1];
|
|
78
|
+
yearString = arr[2];
|
|
79
|
+
} else {
|
|
80
|
+
dayString = arr[2];
|
|
81
|
+
monthString = arr[1];
|
|
82
|
+
yearString = arr[0];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const day = parseInt(dayString, 10);
|
|
86
|
+
const month = parseInt(monthString, 10) - 1;
|
|
87
|
+
const year = parseInt(yearString, 10);
|
|
88
|
+
const date = new Date(year, month, day);
|
|
89
|
+
return date;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const isDate = (inputter, dateString) => {
|
|
93
|
+
const isValid = (string, length, a, b) => {
|
|
94
|
+
return string && string.length === length && isNumeric(string) && a === b;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const arr = dateString.indexOf('/') !== -1 ? dateString.split('/') : dateString.split('-');
|
|
98
|
+
|
|
99
|
+
let dayString;
|
|
100
|
+
let monthString;
|
|
101
|
+
let yearString;
|
|
102
|
+
|
|
103
|
+
if (dateString.indexOf('/') !== -1) {
|
|
104
|
+
dayString = arr[0];
|
|
105
|
+
monthString = arr[1];
|
|
106
|
+
yearString = arr[2];
|
|
107
|
+
} else {
|
|
108
|
+
dayString = arr[2];
|
|
109
|
+
monthString = arr[1];
|
|
110
|
+
yearString = arr[0];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const day = parseInt(dayString, 10);
|
|
114
|
+
const month = parseInt(monthString, 10) - 1;
|
|
115
|
+
const year = parseInt(yearString, 10);
|
|
116
|
+
|
|
117
|
+
// Check formatting first
|
|
118
|
+
const formatValid =
|
|
119
|
+
dateString.length === 10 && isNumeric(dayString) && isNumeric(monthString) && isNumeric(yearString);
|
|
120
|
+
|
|
121
|
+
if (dateString.length > 0 && !formatValid) {
|
|
122
|
+
return VALIDATION_IS_DATE_MESSAGE;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check date is a valid date
|
|
126
|
+
const date = new Date(year, month, day);
|
|
127
|
+
const dayValid = isValid(dayString, 2, date.getDate(), day);
|
|
128
|
+
const monthValid = isValid(monthString, 2, date.getMonth(), month);
|
|
129
|
+
const yearValid = isValid(yearString, 4, date.getFullYear(), year);
|
|
130
|
+
const valid = dayValid && monthValid && yearValid;
|
|
131
|
+
|
|
132
|
+
return dateString.length > 0 && !valid ? VALIDATION_IS_DATE_MESSAGE : '';
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const minDate = (inputter, value, min) => {
|
|
136
|
+
if (isDate(inputter, value) === '') {
|
|
137
|
+
const minDate = stringToDate(min);
|
|
138
|
+
const date = stringToDate(value);
|
|
139
|
+
const displayDate = convertIsoDate(min);
|
|
140
|
+
|
|
141
|
+
if (value.length > 0 && date < minDate) {
|
|
142
|
+
return VALIDATION_MIN_DATE_MESSAGE.replace('$minDate', displayDate);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return '';
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const maxDate = (inputter, value, max) => {
|
|
150
|
+
if (isDate(inputter, value) === '') {
|
|
151
|
+
const maxDate = stringToDate(max);
|
|
152
|
+
const date = stringToDate(value);
|
|
153
|
+
const displayDate = convertIsoDate(max);
|
|
154
|
+
|
|
155
|
+
if (value.length > 0 && date > maxDate) {
|
|
156
|
+
return VALIDATION_MAX_DATE_MESSAGE.replace('$maxDate', displayDate);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return '';
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A function to check whether the value is numeric or not.
|
|
165
|
+
*
|
|
166
|
+
* @function
|
|
167
|
+
* @param {string} value - value to check.
|
|
168
|
+
* @returns {boolean} - True or false.
|
|
169
|
+
* @example
|
|
170
|
+
* // returns false
|
|
171
|
+
* isNumeric('abcd');
|
|
172
|
+
* @example
|
|
173
|
+
* // returns true
|
|
174
|
+
* isNumeric('374');
|
|
175
|
+
*/
|
|
176
|
+
function isNumeric(value) {
|
|
177
|
+
const regex = /[^0-9]/g;
|
|
178
|
+
return value && !value.match(regex);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const hasNumbers = (inputter, value) => {
|
|
182
|
+
return value.length > 0 && !/\d/.test(value) ? VALIDATION_HAS_NUMBERS_MESSAGE : '';
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const hasLetters = (inputter, value) => {
|
|
186
|
+
const regExp = /[a-zA-Z]/g;
|
|
187
|
+
return value.length > 0 && !regExp.test(value) ? VALIDATION_HAS_LETTERS_MESSAGE : '';
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const validations = {
|
|
191
|
+
isRequired,
|
|
192
|
+
isNumber,
|
|
193
|
+
isInteger,
|
|
194
|
+
isEmail,
|
|
195
|
+
minDate,
|
|
196
|
+
maxDate,
|
|
197
|
+
minLength,
|
|
198
|
+
maxLength,
|
|
199
|
+
isBetween,
|
|
200
|
+
isDate,
|
|
201
|
+
hasNumbers,
|
|
202
|
+
hasLetters
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export { validations as default };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { browserstackLauncher } from '@web/test-runner-browserstack';
|
|
2
|
+
|
|
3
|
+
import { serverPlugins } from '@muonic/muon/scripts/rollup-plugins.mjs';
|
|
4
|
+
import { checkRunSnapshots } from './tests/runner/commands.mjs';
|
|
5
|
+
|
|
6
|
+
// options shared between all browsers
|
|
7
|
+
const sharedCapabilities = {
|
|
8
|
+
// your username and key for browserstack, you can get this from your browserstack account
|
|
9
|
+
// it's recommended to store these as environment variables
|
|
10
|
+
'browserstack.user': process.env.BROWSER_STACK_USERNAME,
|
|
11
|
+
'browserstack.key': process.env.BROWSER_STACK_ACCESS_KEY,
|
|
12
|
+
|
|
13
|
+
project: 'Muon',
|
|
14
|
+
name: 'CI tests',
|
|
15
|
+
// if you are running tests in a CI, the build id might be available as an
|
|
16
|
+
// environment variable. this is useful for identifying test runs
|
|
17
|
+
// this is for example the name for github actions
|
|
18
|
+
build: `Muon ${process.env.GITHUB_RUN_NUMBER || 'unknown'}`,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
testRunnerHtml: (testFramework) =>
|
|
23
|
+
`<html>
|
|
24
|
+
<head>
|
|
25
|
+
<script type="module">
|
|
26
|
+
import '@webcomponents/scoped-custom-element-registry';
|
|
27
|
+
</script>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<script>window.process = { env: { NODE_ENV: "development" } }</script>
|
|
31
|
+
<script type="module" src="${testFramework}"></script>
|
|
32
|
+
</body>
|
|
33
|
+
</html>`,
|
|
34
|
+
nodeResolve: true,
|
|
35
|
+
mimeTypes: {
|
|
36
|
+
'**/*.css': 'js'
|
|
37
|
+
},
|
|
38
|
+
plugins: [
|
|
39
|
+
...serverPlugins,
|
|
40
|
+
checkRunSnapshots(false)
|
|
41
|
+
],
|
|
42
|
+
// how many browsers to run concurrently in browserstack. increasing this significantly
|
|
43
|
+
// reduces testing time, but your subscription might limit concurrent connections
|
|
44
|
+
concurrentBrowsers: 2,
|
|
45
|
+
// amount of test files to execute concurrently in a browser. the default value is based
|
|
46
|
+
// on amount of available CPUs locally which is irrelevant when testing remotely
|
|
47
|
+
concurrency: 3,
|
|
48
|
+
browsers: [
|
|
49
|
+
// create a browser launcher per browser you want to test
|
|
50
|
+
// you can get the browser capabilities from the browserstack website
|
|
51
|
+
browserstackLauncher({
|
|
52
|
+
capabilities: {
|
|
53
|
+
...sharedCapabilities,
|
|
54
|
+
browserName: 'Chrome',
|
|
55
|
+
os: 'Windows',
|
|
56
|
+
os_version: '10',
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
browserstackLauncher({
|
|
60
|
+
capabilities: {
|
|
61
|
+
...sharedCapabilities,
|
|
62
|
+
browserName: 'Firefox',
|
|
63
|
+
os: 'Windows',
|
|
64
|
+
os_version: '10',
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
browserstackLauncher({
|
|
68
|
+
capabilities: {
|
|
69
|
+
...sharedCapabilities,
|
|
70
|
+
browserName: 'Edge',
|
|
71
|
+
os: 'Windows',
|
|
72
|
+
os_version: '10',
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
browserstackLauncher({
|
|
76
|
+
capabilities: {
|
|
77
|
+
...sharedCapabilities,
|
|
78
|
+
browserName: 'Safari',
|
|
79
|
+
os: 'OS X',
|
|
80
|
+
os_version: 'Big Sur',
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
browserstackLauncher({
|
|
84
|
+
capabilities: {
|
|
85
|
+
...sharedCapabilities,
|
|
86
|
+
realMobile: true,
|
|
87
|
+
device: 'Google Pixel 5',
|
|
88
|
+
os_version: '12.0',
|
|
89
|
+
browserName: 'Android',
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
browserstackLauncher({
|
|
93
|
+
capabilities: {
|
|
94
|
+
...sharedCapabilities,
|
|
95
|
+
realMobile: true,
|
|
96
|
+
device: 'Samsung Galaxy S20',
|
|
97
|
+
os_version: '10.0',
|
|
98
|
+
browserName: 'Android',
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
// browserstackLauncher({
|
|
102
|
+
// capabilities: {
|
|
103
|
+
// ...sharedCapabilities,
|
|
104
|
+
// realMobile: true,
|
|
105
|
+
// device: 'iPhone 13 Pro',
|
|
106
|
+
// os_version: '15.6',
|
|
107
|
+
// browserName: 'iPhone',
|
|
108
|
+
// },
|
|
109
|
+
// }),
|
|
110
|
+
// browserstackLauncher({
|
|
111
|
+
// capabilities: {
|
|
112
|
+
// ...sharedCapabilities,
|
|
113
|
+
// realMobile: true,
|
|
114
|
+
// device: 'iPhone SE 2020',
|
|
115
|
+
// os_version: '13',
|
|
116
|
+
// browserName: 'iPhone',
|
|
117
|
+
// },
|
|
118
|
+
// }),
|
|
119
|
+
],
|
|
120
|
+
browserStartTimeout: 60000,
|
|
121
|
+
testsStartTimeout: 60000,
|
|
122
|
+
testsFinishTimeout: 120000,
|
|
123
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { playwrightLauncher } from '@web/test-runner-playwright';
|
|
2
|
+
import { serverPlugins } from '@muonic/muon/scripts/rollup-plugins.mjs';
|
|
3
|
+
import { checkRunSnapshots } from './tests/runner/commands.mjs';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
testRunnerHtml: (testFramework) =>
|
|
7
|
+
`<html>
|
|
8
|
+
<head>
|
|
9
|
+
<script type="module">
|
|
10
|
+
import '@webcomponents/scoped-custom-element-registry';
|
|
11
|
+
</script>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<script>window.process = { env: { NODE_ENV: "development" } }</script>
|
|
15
|
+
<script type="module" src="${testFramework}"></script>
|
|
16
|
+
</body>
|
|
17
|
+
</html>`,
|
|
18
|
+
nodeResolve: true,
|
|
19
|
+
mimeTypes: {
|
|
20
|
+
'**/*.css': 'js'
|
|
21
|
+
},
|
|
22
|
+
browsers: [
|
|
23
|
+
playwrightLauncher({ product: 'chromium' }),
|
|
24
|
+
playwrightLauncher({ product: 'firefox' }),
|
|
25
|
+
playwrightLauncher({ product: 'webkit' })
|
|
26
|
+
],
|
|
27
|
+
browserStartTimeout: 30000, // default 30000
|
|
28
|
+
testsStartTimeout: 20000, // default 10000
|
|
29
|
+
testsFinishTimeout: 60000, // default 20000
|
|
30
|
+
concurrentBrowsers: 2,
|
|
31
|
+
concurrency: 2,
|
|
32
|
+
plugins: [
|
|
33
|
+
...serverPlugins,
|
|
34
|
+
checkRunSnapshots()
|
|
35
|
+
],
|
|
36
|
+
coverageConfig: {
|
|
37
|
+
threshold: {
|
|
38
|
+
statements: 99,
|
|
39
|
+
branches: 99,
|
|
40
|
+
functions: 99,
|
|
41
|
+
lines: 99
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|