|
1 | | -import warning from 'warning'; |
2 | | -import hash from '@emotion/hash'; |
| 1 | +import { assert } from 'chai'; |
| 2 | +import consoleErrorMock from 'test/utils/consoleErrorMock'; |
| 3 | +import createGenerateClassName from './createGenerateClassName'; |
3 | 4 |
|
4 | | -function safePrefix(classNamePrefix) { |
5 | | - const prefix = String(classNamePrefix); |
6 | | - warning(prefix.length < 256, `Material-UI: the class name prefix is too long: ${prefix}.`); |
7 | | - return prefix; |
8 | | -} |
| 5 | +describe('createGenerateClassName', () => { |
| 6 | + const generateClassName = createGenerateClassName(); |
9 | 7 |
|
10 | | -const themeHashCache = {}; |
| 8 | + it('should generate a class name', () => { |
| 9 | + assert.strictEqual( |
| 10 | + generateClassName( |
| 11 | + { |
| 12 | + key: 'key', |
| 13 | + }, |
| 14 | + { |
| 15 | + options: { |
| 16 | + theme: {}, |
| 17 | + classNamePrefix: 'classNamePrefix', |
| 18 | + }, |
| 19 | + }, |
| 20 | + ), |
| 21 | + 'classNamePrefix-key-1', |
| 22 | + ); |
| 23 | + }); |
11 | 24 |
|
12 | | -// Returns a function which generates unique class names based on counters. |
13 | | -// When new generator function is created, rule counter is reset. |
14 | | -// We need to reset the rule counter for SSR for each request. |
15 | | -// |
16 | | -// It's inspired by |
17 | | -// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js |
18 | | -export default function createGenerateClassName(options = {}) { |
19 | | - const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss', seed = '' } = options; |
20 | | - let ruleCounter = 0; |
| 25 | + it('should increase the counter only when needed', () => { |
| 26 | + assert.strictEqual( |
| 27 | + generateClassName( |
| 28 | + { |
| 29 | + key: 'key', |
| 30 | + }, |
| 31 | + { |
| 32 | + options: { |
| 33 | + theme: {}, |
| 34 | + classNamePrefix: 'classNamePrefix', |
| 35 | + }, |
| 36 | + }, |
| 37 | + ), |
| 38 | + 'classNamePrefix-key-2', |
| 39 | + ); |
| 40 | + assert.strictEqual( |
| 41 | + generateClassName( |
| 42 | + { |
| 43 | + key: 'key', |
| 44 | + }, |
| 45 | + { |
| 46 | + options: { |
| 47 | + link: true, |
| 48 | + classNamePrefix: 'classNamePrefix', |
| 49 | + }, |
| 50 | + }, |
| 51 | + ), |
| 52 | + 'classNamePrefix-key-3', |
| 53 | + ); |
| 54 | + assert.strictEqual( |
| 55 | + generateClassName( |
| 56 | + { |
| 57 | + key: 'key', |
| 58 | + }, |
| 59 | + { |
| 60 | + options: { |
| 61 | + link: true, |
| 62 | + classNamePrefix: 'classNamePrefix', |
| 63 | + }, |
| 64 | + }, |
| 65 | + ), |
| 66 | + 'classNamePrefix-key-4', |
| 67 | + ); |
| 68 | + }); |
21 | 69 |
|
22 | | - return (rule, styleSheet) => { |
23 | | - const isStatic = !styleSheet.options.link; |
24 | | - |
25 | | - if (dangerouslyUseGlobalCSS && styleSheet && styleSheet.options.name && isStatic) { |
26 | | - return `${safePrefix(styleSheet.options.name)}-${rule.key}`; |
27 | | - } |
28 | | - |
29 | | - let suffix; |
30 | | - |
31 | | - // It's a static rule. |
32 | | - if (isStatic) { |
33 | | - let themeHash = themeHashCache[styleSheet.options.theme]; |
34 | | - if (!themeHash) { |
35 | | - themeHash = hash(JSON.stringify(styleSheet.options.theme)); |
36 | | - themeHashCache[styleSheet.theme] = themeHash; |
37 | | - } |
38 | | - const raw = styleSheet.rules.raw[rule.key]; |
39 | | - suffix = hash(`${themeHash}${rule.key}${JSON.stringify(raw)}`); |
40 | | - } |
41 | | - |
42 | | - if (!suffix) { |
43 | | - ruleCounter += 1; |
44 | | - warning( |
45 | | - ruleCounter < 1e10, |
46 | | - [ |
47 | | - 'Material-UI: you might have a memory leak.', |
48 | | - 'The ruleCounter is not supposed to grow that much.', |
49 | | - ].join(''), |
| 70 | + describe('classNamePrefix', () => { |
| 71 | + it('should work without a classNamePrefix', () => { |
| 72 | + const generateClassName2 = createGenerateClassName(); |
| 73 | + assert.strictEqual( |
| 74 | + generateClassName2( |
| 75 | + { key: 'root' }, |
| 76 | + { |
| 77 | + options: {}, |
| 78 | + }, |
| 79 | + ), |
| 80 | + 'root-1', |
50 | 81 | ); |
| 82 | + }); |
| 83 | + }); |
51 | 84 |
|
52 | | - suffix = ruleCounter; |
| 85 | + describe('production', () => { |
| 86 | + // Only run the test on node. |
| 87 | + if (!/jsdom/.test(window.navigator.userAgent)) { |
| 88 | + return; |
53 | 89 | } |
54 | 90 |
|
55 | | - if (process.env.NODE_ENV === 'production') { |
56 | | - return `${productionPrefix}${seed}${suffix}`; |
57 | | - } |
| 91 | + let nodeEnv; |
| 92 | + const env = process.env; |
58 | 93 |
|
59 | | - // Help with debuggability. |
60 | | - if (styleSheet.options.classNamePrefix) { |
61 | | - return `${safePrefix(styleSheet.options.classNamePrefix)}-${rule.key}-${seed}${suffix}`; |
62 | | - } |
| 94 | + before(() => { |
| 95 | + nodeEnv = env.NODE_ENV; |
| 96 | + env.NODE_ENV = 'production'; |
| 97 | + consoleErrorMock.spy(); |
| 98 | + }); |
| 99 | + |
| 100 | + after(() => { |
| 101 | + env.NODE_ENV = nodeEnv; |
| 102 | + consoleErrorMock.reset(); |
| 103 | + }); |
63 | 104 |
|
64 | | - return `${rule.key}-${seed}${suffix}`; |
65 | | - }; |
66 | | -} |
| 105 | + it('should output a short representation', () => { |
| 106 | + const rule = { key: 'root' }; |
| 107 | + const styleSheet = { |
| 108 | + rules: { raw: {} }, |
| 109 | + options: {}, |
| 110 | + }; |
| 111 | + const generateClassName2 = createGenerateClassName(); |
| 112 | + assert.strictEqual(generateClassName2(rule, styleSheet), 'jss1'); |
| 113 | + }); |
| 114 | + }); |
| 115 | +}); |
0 commit comments