-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[test] Add missing styles tests (#15376)
- Loading branch information
1 parent
138cc30
commit a231a4c
Showing
2 changed files
with
502 additions
and
108 deletions.
There are no files selected for viewing
305 changes: 251 additions & 54 deletions
305
packages/material-ui-styles/src/createGenerateClassName/createGenerateClassName.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,263 @@ | ||
import warning from 'warning'; | ||
import hash from '@emotion/hash'; | ||
import { assert } from 'chai'; | ||
import consoleErrorMock from 'test/utils/consoleErrorMock'; | ||
import createGenerateClassName from './createGenerateClassName'; | ||
|
||
function safePrefix(classNamePrefix) { | ||
const prefix = String(classNamePrefix); | ||
warning(prefix.length < 256, `Material-UI: the class name prefix is too long: ${prefix}.`); | ||
return prefix; | ||
} | ||
describe('createGenerateClassName', () => { | ||
const generateClassName = createGenerateClassName(); | ||
const generateClassNameGlobal = createGenerateClassName({ dangerouslyUseGlobalCSS: true }); | ||
|
||
const themeHashCache = {}; | ||
describe('dangerouslyUseGlobalCSS', () => { | ||
it('should have a stable classname', () => { | ||
assert.strictEqual( | ||
generateClassNameGlobal( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
options: { | ||
name: 'MuiGrid', | ||
}, | ||
}, | ||
), | ||
'MuiGrid-key', | ||
); | ||
assert.strictEqual( | ||
generateClassNameGlobal( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key: () => ({}), | ||
}, | ||
}, | ||
options: { | ||
link: true, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key-1', | ||
); | ||
}); | ||
}); | ||
|
||
// Returns a function which generates unique class names based on counters. | ||
// When new generator function is created, rule counter is reset. | ||
// We need to reset the rule counter for SSR for each request. | ||
// | ||
// It's inspired by | ||
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js | ||
export default function createGenerateClassName(options = {}) { | ||
const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss', seed = '' } = options; | ||
let ruleCounter = 0; | ||
it('should generate a class name', () => { | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key: { | ||
flex: 1, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: {}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key-1', | ||
); | ||
}); | ||
|
||
return (rule, styleSheet) => { | ||
const isStatic = !styleSheet.options.link; | ||
it('should increase the counter only when needed', () => { | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key: { | ||
flex: 1, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: {}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key-2', | ||
); | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key: () => ({}), | ||
}, | ||
}, | ||
options: { | ||
link: true, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key-3', | ||
); | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key: () => ({}), | ||
}, | ||
}, | ||
options: { | ||
link: true, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key-4', | ||
); | ||
}); | ||
|
||
if (dangerouslyUseGlobalCSS && styleSheet && styleSheet.options.name && isStatic) { | ||
return `${safePrefix(styleSheet.options.name)}-${rule.key}`; | ||
} | ||
it('should use the theme object, rule key and the style raw', () => { | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key1', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key1: { | ||
flex: 1, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: {}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key1-5', | ||
); | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key2', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key2: { | ||
flex: 1, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: {}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key2-6', | ||
); | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key2', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key2: { | ||
flex: 2, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: {}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key2-7', | ||
); | ||
assert.strictEqual( | ||
generateClassName( | ||
{ | ||
key: 'key2', | ||
}, | ||
{ | ||
rules: { | ||
raw: { | ||
key2: { | ||
flex: 2, | ||
}, | ||
}, | ||
}, | ||
options: { | ||
theme: { | ||
spacing: 4, | ||
}, | ||
classNamePrefix: 'classNamePrefix', | ||
}, | ||
}, | ||
), | ||
'classNamePrefix-key2-8', | ||
); | ||
}); | ||
|
||
let suffix; | ||
describe('classNamePrefix', () => { | ||
it('should work without a classNamePrefix', () => { | ||
const rule = { key: 'root' }; | ||
const styleSheet = { | ||
rules: { raw: {} }, | ||
options: {}, | ||
}; | ||
const generateClassName2 = createGenerateClassName(); | ||
assert.strictEqual(generateClassName2(rule, styleSheet), 'root-1'); | ||
}); | ||
}); | ||
|
||
// It's a static rule. | ||
if (isStatic) { | ||
let themeHash = themeHashCache[styleSheet.options.theme]; | ||
if (!themeHash) { | ||
themeHash = hash(JSON.stringify(styleSheet.options.theme)); | ||
themeHashCache[styleSheet.theme] = themeHash; | ||
} | ||
const raw = styleSheet.rules.raw[rule.key]; | ||
suffix = hash(`${themeHash}${rule.key}${JSON.stringify(raw)}`); | ||
describe('production', () => { | ||
// Only run the test on node. | ||
if (!/jsdom/.test(window.navigator.userAgent)) { | ||
return; | ||
} | ||
|
||
if (!suffix) { | ||
ruleCounter += 1; | ||
warning( | ||
ruleCounter < 1e10, | ||
[ | ||
'Material-UI: you might have a memory leak.', | ||
'The ruleCounter is not supposed to grow that much.', | ||
].join(''), | ||
); | ||
|
||
suffix = ruleCounter; | ||
} | ||
let nodeEnv; | ||
const env = process.env; | ||
|
||
if (process.env.NODE_ENV === 'production') { | ||
return `${productionPrefix}${seed}${suffix}`; | ||
} | ||
before(() => { | ||
nodeEnv = env.NODE_ENV; | ||
env.NODE_ENV = 'production'; | ||
consoleErrorMock.spy(); | ||
}); | ||
|
||
// Help with debuggability. | ||
if (styleSheet.options.classNamePrefix) { | ||
return `${safePrefix(styleSheet.options.classNamePrefix)}-${rule.key}-${seed}${suffix}`; | ||
} | ||
after(() => { | ||
env.NODE_ENV = nodeEnv; | ||
consoleErrorMock.reset(); | ||
}); | ||
|
||
return `${rule.key}-${seed}${suffix}`; | ||
}; | ||
} | ||
it('should output a short representation', () => { | ||
const rule = { key: 'root' }; | ||
const styleSheet = { | ||
rules: { raw: {} }, | ||
options: {}, | ||
}; | ||
const generateClassName2 = createGenerateClassName(); | ||
assert.strictEqual(generateClassName2(rule, styleSheet), 'jss1'); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.