You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

611 lines
21 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. // Jasmine unit tests
  2. // To run tests, run these commands from the project root:
  3. // 1. `npm install -g jasmine-node`
  4. // 2. `jasmine-node spec`
  5. /* global describe, it, expect */
  6. 'use strict';
  7. var postcss = require('postcss');
  8. var pxToViewport = require('..');
  9. var basicCSS = '.rule { font-size: 15px }';
  10. var { filterPropList } = require('../src/prop-list-matcher');
  11. describe('px-to-viewport', function() {
  12. it('should work on the readme example', function () {
  13. var input = 'h1 { margin: 0 0 20px; font-size: 32px; line-height: 2; letter-spacing: 1px; }';
  14. var output = 'h1 { margin: 0 0 6.25vw; font-size: 10vw; line-height: 2; letter-spacing: 1px; }';
  15. var processed = postcss(pxToViewport()).process(input).css;
  16. expect(processed).toBe(output);
  17. });
  18. it('should replace the px unit with vw', function () {
  19. var processed = postcss(pxToViewport()).process(basicCSS).css;
  20. var expected = '.rule { font-size: 4.6875vw }';
  21. expect(processed).toBe(expected);
  22. });
  23. it('should handle < 1 values and values without a leading 0', function () {
  24. var rules = '.rule { margin: 0.5rem .5px -0.2px -.2em }';
  25. var expected = '.rule { margin: 0.5rem 0.15625vw -0.0625vw -.2em }';
  26. var options = {
  27. minPixelValue: 0
  28. };
  29. var processed = postcss(pxToViewport(options)).process(rules).css;
  30. expect(processed).toBe(expected);
  31. });
  32. it('should remain unitless if 0', function () {
  33. var expected = '.rule { font-size: 0px; font-size: 0; }';
  34. var processed = postcss(pxToViewport()).process(expected).css;
  35. expect(processed).toBe(expected);
  36. });
  37. it('should not add properties that already exist', function () {
  38. var expected = '.rule { font-size: 16px; font-size: 5vw; }';
  39. var processed = postcss(pxToViewport()).process(expected).css;
  40. expect(processed).toBe(expected);
  41. });
  42. it('should not replace units inside mediaQueries by default', function() {
  43. var expected = '@media (min-width: 500px) { .rule { font-size: 16px } }';
  44. var processed = postcss(pxToViewport()).process('@media (min-width: 500px) { .rule { font-size: 16px } }').css;
  45. expect(processed).toBe(expected);
  46. })
  47. });
  48. describe('value parsing', function() {
  49. it('should not replace values in double quotes or single quotes', function () {
  50. var options = {
  51. propList: ['*']
  52. };
  53. var rules = '.rule { content: \'16px\'; font-family: "16px"; font-size: 16px; }';
  54. var expected = '.rule { content: \'16px\'; font-family: "16px"; font-size: 5vw; }';
  55. var processed = postcss(pxToViewport(options)).process(rules).css;
  56. expect(processed).toBe(expected);
  57. });
  58. it('should not replace values in `url()`', function () {
  59. var rules = '.rule { background: url(16px.jpg); font-size: 16px; }';
  60. var expected = '.rule { background: url(16px.jpg); font-size: 5vw; }';
  61. var processed = postcss(pxToViewport()).process(rules).css;
  62. expect(processed).toBe(expected);
  63. });
  64. it('should not replace values with an uppercase P or X', function () {
  65. var rules = '.rule { margin: 12px calc(100% - 14PX); height: calc(100% - 20px); font-size: 12Px; line-height: 16px; }';
  66. var expected = '.rule { margin: 3.75vw calc(100% - 14PX); height: calc(100% - 6.25vw); font-size: 12Px; line-height: 5vw; }';
  67. var processed = postcss(pxToViewport()).process(rules).css;
  68. expect(processed).toBe(expected);
  69. });
  70. });
  71. describe('unitToConvert', function() {
  72. it('should ignore non px values by default', function () {
  73. var expected = '.rule { font-size: 2em }';
  74. var processed = postcss(pxToViewport()).process(expected).css;
  75. expect(processed).toBe(expected);
  76. });
  77. it('should convert only values described in options', function () {
  78. var rules = '.rule { font-size: 5em; line-height: 2px }';
  79. var expected = '.rule { font-size: 1.5625vw; line-height: 2px }';
  80. var options = {
  81. unitToConvert: 'em'
  82. };
  83. var processed = postcss(pxToViewport(options)).process(rules).css;
  84. expect(processed).toBe(expected);
  85. });
  86. });
  87. describe('viewportWidth', function() {
  88. it('should should replace using 320px by default', function() {
  89. var expected = '.rule { font-size: 4.6875vw }';
  90. var processed = postcss(pxToViewport()).process(basicCSS).css;
  91. expect(processed).toBe(expected);
  92. });
  93. it('should replace using viewportWidth from options', function() {
  94. var expected = '.rule { font-size: 3.125vw }';
  95. var options = {
  96. viewportWidth: 480
  97. };
  98. var processed = postcss(pxToViewport(options)).process(basicCSS).css;
  99. expect(processed).toBe(expected);
  100. })
  101. });
  102. describe('unitPrecision', function () {
  103. it('should replace using a decimal of 2 places', function () {
  104. var expected = '.rule { font-size: 4.69vw }';
  105. var options = {
  106. unitPrecision: 2
  107. };
  108. var processed = postcss(pxToViewport(options)).process(basicCSS).css;
  109. expect(processed).toBe(expected);
  110. });
  111. });
  112. describe('viewportUnit', function() {
  113. it('should replace using unit from options', function() {
  114. var rules = '.rule { margin-top: 15px }';
  115. var expected = '.rule { margin-top: 4.6875vh }';
  116. var options = {
  117. viewportUnit: 'vh'
  118. };
  119. var processed = postcss(pxToViewport(options)).process(rules).css;
  120. expect(processed).toBe(expected);
  121. });
  122. });
  123. describe('fontViewportUnit', function() {
  124. it('should replace only font-size using unit from options', function() {
  125. var rules = '.rule { margin-top: 15px; font-size: 8px; }';
  126. var expected = '.rule { margin-top: 4.6875vw; font-size: 2.5vmax; }';
  127. var options = {
  128. fontViewportUnit: 'vmax'
  129. };
  130. var processed = postcss(pxToViewport(options)).process(rules).css;
  131. expect(processed).toBe(expected);
  132. });
  133. });
  134. describe('selectorBlackList', function () {
  135. it('should ignore selectors in the selector black list', function () {
  136. var rules = '.rule { font-size: 15px } .rule2 { font-size: 15px }';
  137. var expected = '.rule { font-size: 4.6875vw } .rule2 { font-size: 15px }';
  138. var options = {
  139. selectorBlackList: ['.rule2']
  140. };
  141. var processed = postcss(pxToViewport(options)).process(rules).css;
  142. expect(processed).toBe(expected);
  143. });
  144. it('should ignore every selector with `body$`', function () {
  145. var rules = 'body { font-size: 16px; } .class-body$ { font-size: 16px; } .simple-class { font-size: 16px; }';
  146. var expected = 'body { font-size: 5vw; } .class-body$ { font-size: 16px; } .simple-class { font-size: 5vw; }';
  147. var options = {
  148. selectorBlackList: ['body$']
  149. };
  150. var processed = postcss(pxToViewport(options)).process(rules).css;
  151. expect(processed).toBe(expected);
  152. });
  153. it('should only ignore exactly `body`', function () {
  154. var rules = 'body { font-size: 16px; } .class-body { font-size: 16px; } .simple-class { font-size: 16px; }';
  155. var expected = 'body { font-size: 16px; } .class-body { font-size: 5vw; } .simple-class { font-size: 5vw; }';
  156. var options = {
  157. selectorBlackList: [/^body$/]
  158. };
  159. var processed = postcss(pxToViewport(options)).process(rules).css;
  160. expect(processed).toBe(expected);
  161. });
  162. });
  163. describe('mediaQuery', function () {
  164. it('should replace px inside media queries if opts.mediaQuery', function() {
  165. var options = {
  166. mediaQuery: true
  167. };
  168. var processed = postcss(pxToViewport(options)).process('@media (min-width: 500px) { .rule { font-size: 16px } }').css;
  169. var expected = '@media (min-width: 500px) { .rule { font-size: 5vw } }';
  170. expect(processed).toBe(expected);
  171. });
  172. it('should not replace px inside media queries if not opts.mediaQuery', function() {
  173. var options = {
  174. mediaQuery: false
  175. };
  176. var processed = postcss(pxToViewport(options)).process('@media (min-width: 500px) { .rule { font-size: 16px } }').css;
  177. var expected = '@media (min-width: 500px) { .rule { font-size: 16px } }';
  178. expect(processed).toBe(expected);
  179. });
  180. it('should replace px inside media queries if it has params orientation landscape and landscape option', function() {
  181. var options = {
  182. mediaQuery: true,
  183. landscape: true
  184. };
  185. var processed = postcss(pxToViewport(options)).process('@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 16px } }').css;
  186. var expected = '@media (orientation-landscape) and (min-width: 500px) { .rule { font-size: 2.8169vw } }';
  187. expect(processed).toBe(expected);
  188. });
  189. });
  190. describe('propList', function () {
  191. it('should only replace properties in the prop list', function () {
  192. var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
  193. var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 5px; padding: 5px; padding-right: 5vw }';
  194. var options = {
  195. propList: ['*font*', 'margin*', '!margin-left', '*-right', 'pad']
  196. };
  197. var processed = postcss(pxToViewport(options)).process(css).css;
  198. expect(processed).toBe(expected);
  199. });
  200. it('should only replace properties in the prop list with wildcard', function () {
  201. var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
  202. var expected = '.rule { font-size: 16px; margin: 5vw; margin-left: 5px; padding: 5px; padding-right: 16px }';
  203. var options = {
  204. propList: ['*', '!margin-left', '!*padding*', '!font*']
  205. };
  206. var processed = postcss(pxToViewport(options)).process(css).css;
  207. expect(processed).toBe(expected);
  208. });
  209. it('should replace all properties when prop list is not given', function () {
  210. var rules = '.rule { margin: 16px; font-size: 15px }';
  211. var expected = '.rule { margin: 5vw; font-size: 4.6875vw }';
  212. var processed = postcss(pxToViewport()).process(rules).css;
  213. expect(processed).toBe(expected);
  214. });
  215. });
  216. describe('minPixelValue', function () {
  217. it('should not replace values below minPixelValue', function () {
  218. var options = {
  219. propWhiteList: [],
  220. minPixelValue: 2
  221. };
  222. var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
  223. var expected = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }';
  224. var processed = postcss(pxToViewport(options)).process(rules).css;
  225. expect(processed).toBe(expected);
  226. });
  227. });
  228. describe('exclude', function () {
  229. var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
  230. var covered = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }';
  231. it('when using regex at the time, the style should not be overwritten.', function () {
  232. var options = {
  233. exclude: /\/node_modules\//
  234. };
  235. var processed = postcss(pxToViewport(options)).process(rules, {
  236. from: '/node_modules/main.css'
  237. }).css;
  238. expect(processed).toBe(rules);
  239. });
  240. it('when using regex at the time, the style should be overwritten.', function () {
  241. var options = {
  242. exclude: /\/node_modules\//
  243. };
  244. var processed = postcss(pxToViewport(options)).process(rules, {
  245. from: '/example/main.css'
  246. }).css;
  247. expect(processed).toBe(covered);
  248. });
  249. it('when using array at the time, the style should not be overwritten.', function () {
  250. var options = {
  251. exclude: [/\/node_modules\//, /\/exclude\//]
  252. };
  253. var processed = postcss(pxToViewport(options)).process(rules, {
  254. from: '/exclude/main.css'
  255. }).css;
  256. expect(processed).toBe(rules);
  257. });
  258. it('when using array at the time, the style should be overwritten.', function () {
  259. var options = {
  260. exclude: [/\/node_modules\//, /\/exclude\//]
  261. };
  262. var processed = postcss(pxToViewport(options)).process(rules, {
  263. from: '/example/main.css'
  264. }).css;
  265. expect(processed).toBe(covered);
  266. });
  267. });
  268. describe('include', function () {
  269. var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
  270. var covered = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }';
  271. it('when using regex at the time, the style should not be overwritten.', function () {
  272. var options = {
  273. include: /\/mobile\//
  274. };
  275. var processed = postcss(pxToViewport(options)).process(rules, {
  276. from: '/pc/main.css'
  277. }).css;
  278. expect(processed).toBe(rules);
  279. });
  280. it('when using regex at the time, the style should be overwritten.', function () {
  281. var options = {
  282. include: /\/mobile\//
  283. };
  284. var processed = postcss(pxToViewport(options)).process(rules, {
  285. from: '/mobile/main.css'
  286. }).css;
  287. expect(processed).toBe(covered);
  288. });
  289. it('when using array at the time, the style should not be overwritten.', function () {
  290. var options = {
  291. include: [/\/flexible\//, /\/mobile\//]
  292. };
  293. var processed = postcss(pxToViewport(options)).process(rules, {
  294. from: '/pc/main.css'
  295. }).css;
  296. expect(processed).toBe(rules);
  297. });
  298. it('when using array at the time, the style should be overwritten.', function () {
  299. var options = {
  300. include: [/\/flexible\//, /\/mobile\//]
  301. };
  302. var processed = postcss(pxToViewport(options)).process(rules, {
  303. from: '/flexible/main.css'
  304. }).css;
  305. expect(processed).toBe(covered);
  306. });
  307. });
  308. describe('include-and-exclude', function () {
  309. var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
  310. var covered = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }';
  311. it('when using regex at the time, the style should not be overwritten.', function () {
  312. var options = {
  313. include: /\/mobile\//,
  314. exclude: /\/not-transform\//
  315. };
  316. var processed = postcss(pxToViewport(options)).process(rules, {
  317. from: '/mobile/not-transform/main.css'
  318. }).css;
  319. expect(processed).toBe(rules);
  320. });
  321. it('when using regex at the time, the style should be overwritten.', function () {
  322. var options = {
  323. include: /\/mobile\//,
  324. exclude: /\/not-transform\//
  325. };
  326. var processed = postcss(pxToViewport(options)).process(rules, {
  327. from: '/mobile/style/main.css'
  328. }).css;
  329. expect(processed).toBe(covered);
  330. });
  331. it('when using array at the time, the style should not be overwritten.', function () {
  332. var options = {
  333. include: [/\/flexible\//, /\/mobile\//],
  334. exclude: [/\/not-transform\//, /pc/]
  335. };
  336. var processed = postcss(pxToViewport(options)).process(rules, {
  337. from: '/flexible/not-transform/main.css'
  338. }).css;
  339. expect(processed).toBe(rules);
  340. });
  341. it('when using regex at the time, the style should be overwritten.', function () {
  342. var options = {
  343. include: [/\/flexible\//, /\/mobile\//],
  344. exclude: [/\/not-transform\//, /pc/]
  345. };
  346. var processed = postcss(pxToViewport(options)).process(rules, {
  347. from: '/mobile/style/main.css'
  348. }).css;
  349. expect(processed).toBe(covered);
  350. });
  351. });
  352. describe('regex', function () {
  353. var rules = '.rule { border: 1px solid #000; font-size: 16px; margin: 1px 10px; }';
  354. var covered = '.rule { border: 1px solid #000; font-size: 5vw; margin: 1px 3.125vw; }';
  355. it('when using regex at the time, the style should not be overwritten.', function () {
  356. var options = {
  357. exclude: /pc/
  358. };
  359. var processed = postcss(pxToViewport(options)).process(rules, {
  360. from: '/pc-project/main.css'
  361. }).css;
  362. expect(processed).toBe(rules);
  363. });
  364. it('when using regex at the time, the style should be overwritten.', function () {
  365. var options = {
  366. exclude: /\/pc\//
  367. };
  368. var processed = postcss(pxToViewport(options)).process(rules, {
  369. from: '/pc-project/main.css'
  370. }).css;
  371. expect(processed).toBe(covered);
  372. });
  373. it('when using regex at the time, the style should not be overwritten.', function () {
  374. var options = {
  375. include: /\/pc\//
  376. };
  377. var processed = postcss(pxToViewport(options)).process(rules, {
  378. from: '/pc-project/main.css'
  379. }).css;
  380. expect(processed).toBe(rules);
  381. });
  382. it('when using regex at the time, the style should be overwritten.', function () {
  383. var options = {
  384. include: /pc/
  385. };
  386. var processed = postcss(pxToViewport(options)).process(rules, {
  387. from: '/pc-project/main.css'
  388. }).css;
  389. expect(processed).toBe(covered);
  390. });
  391. });
  392. describe('replace', function () {
  393. it('should leave fallback pixel unit with root em value', function () {
  394. var options = {
  395. replace: false
  396. };
  397. var processed = postcss(pxToViewport(options)).process(basicCSS).css;
  398. var expected = '.rule { font-size: 15px; font-size: 4.6875vw }';
  399. expect(processed).toBe(expected);
  400. });
  401. });
  402. describe('filter-prop-list', function () {
  403. it('should find "exact" matches from propList', function () {
  404. var propList = ['font-size', 'margin', '!padding', '*border*', '*', '*y', '!*font*'];
  405. var expected = 'font-size,margin';
  406. expect(filterPropList.exact(propList).join()).toBe(expected);
  407. });
  408. it('should find "contain" matches from propList and reduce to string', function () {
  409. var propList = ['font-size', '*margin*', '!padding', '*border*', '*', '*y', '!*font*'];
  410. var expected = 'margin,border';
  411. expect(filterPropList.contain(propList).join()).toBe(expected);
  412. });
  413. it('should find "start" matches from propList and reduce to string', function () {
  414. var propList = ['font-size', '*margin*', '!padding', 'border*', '*', '*y', '!*font*'];
  415. var expected = 'border';
  416. expect(filterPropList.startWith(propList).join()).toBe(expected);
  417. });
  418. it('should find "end" matches from propList and reduce to string', function () {
  419. var propList = ['font-size', '*margin*', '!padding', 'border*', '*', '*y', '!*font*'];
  420. var expected = 'y';
  421. expect(filterPropList.endWith(propList).join()).toBe(expected);
  422. });
  423. it('should find "not" matches from propList and reduce to string', function () {
  424. var propList = ['font-size', '*margin*', '!padding', 'border*', '*', '*y', '!*font*'];
  425. var expected = 'padding';
  426. expect(filterPropList.notExact(propList).join()).toBe(expected);
  427. });
  428. it('should find "not contain" matches from propList and reduce to string', function () {
  429. var propList = ['font-size', '*margin*', '!padding', '!border*', '*', '*y', '!*font*'];
  430. var expected = 'font';
  431. expect(filterPropList.notContain(propList).join()).toBe(expected);
  432. });
  433. it('should find "not start" matches from propList and reduce to string', function () {
  434. var propList = ['font-size', '*margin*', '!padding', '!border*', '*', '*y', '!*font*'];
  435. var expected = 'border';
  436. expect(filterPropList.notStartWith(propList).join()).toBe(expected);
  437. });
  438. it('should find "not end" matches from propList and reduce to string', function () {
  439. var propList = ['font-size', '*margin*', '!padding', '!border*', '*', '!*y', '!*font*'];
  440. var expected = 'y';
  441. expect(filterPropList.notEndWith(propList).join()).toBe(expected);
  442. });
  443. });
  444. describe('landscape', function() {
  445. it('should add landscape atRule', function() {
  446. var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
  447. var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 2.8169vw; margin: 2.8169vw; margin-left: 0.88028vw; padding: 0.88028vw; padding-right: 2.8169vw } }';
  448. var options = {
  449. landscape: true
  450. };
  451. var processed = postcss(pxToViewport(options)).process(css).css;
  452. expect(processed).toBe(expected);
  453. });
  454. it('should add landscape atRule with specified landscapeUnits', function() {
  455. var css = '.rule { font-size: 16px; margin: 16px; margin-left: 5px; padding: 5px; padding-right: 16px }';
  456. var expected = '.rule { font-size: 5vw; margin: 5vw; margin-left: 1.5625vw; padding: 1.5625vw; padding-right: 5vw }@media (orientation: landscape) {.rule { font-size: 2.8169vh; margin: 2.8169vh; margin-left: 0.88028vh; padding: 0.88028vh; padding-right: 2.8169vh } }';
  457. var options = {
  458. landscape: true,
  459. landscapeUnit: 'vh'
  460. };
  461. var processed = postcss(pxToViewport(options)).process(css).css;
  462. expect(processed).toBe(expected);
  463. });
  464. it('should not add landscape atRule in mediaQueries', function() {
  465. var css = '@media (min-width: 500px) { .rule { font-size: 16px } }';
  466. var expected = '@media (min-width: 500px) { .rule { font-size: 5vw } }';
  467. var options = {
  468. landscape: true,
  469. mediaQuery: true
  470. };
  471. var processed = postcss(pxToViewport(options)).process(css).css;
  472. expect(processed).toBe(expected);
  473. });
  474. it('should not replace values inside landscape atRule', function() {
  475. var options = {
  476. replace: false,
  477. landscape: true
  478. };
  479. var processed = postcss(pxToViewport(options)).process(basicCSS).css;
  480. var expected = '.rule { font-size: 15px; font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 2.64085vw } }';
  481. expect(processed).toBe(expected);
  482. });
  483. it('should add landscape atRule with specified landscapeWidth', function() {
  484. var options = {
  485. landscape: true,
  486. landscapeWidth: 768
  487. };
  488. var processed = postcss(pxToViewport(options)).process(basicCSS).css;
  489. var expected = '.rule { font-size: 4.6875vw }@media (orientation: landscape) {.rule { font-size: 1.95313vw } }';
  490. expect(processed).toBe(expected);
  491. });
  492. it('should not add landscape atRule if it has no nodes', function() {
  493. var css = '.rule { font-size: 15vw }';
  494. var options = {
  495. landscape: true
  496. };
  497. var processed = postcss(pxToViewport(options)).process(css).css;
  498. var expected = '.rule { font-size: 15vw }';
  499. expect(processed).toBe(expected);
  500. })
  501. });