PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/training-web/vendor/bundle/gems/sass-3.2.9/test/sass/scss/scss_test.rb

https://bitbucket.org/ohimmelreich/asalia-training
Ruby | 2035 lines | 1977 code | 53 blank | 5 comment | 0 complexity | 4ea4643c2a3a6fc377c253a9eb0bb19e MD5 | raw file
  1. #!/usr/bin/env ruby
  2. # -*- coding: utf-8 -*-
  3. require File.dirname(__FILE__) + '/test_helper'
  4. class ScssTest < Test::Unit::TestCase
  5. include ScssTestHelper
  6. ## One-Line Comments
  7. def test_one_line_comments
  8. assert_equal <<CSS, render(<<SCSS)
  9. .foo {
  10. baz: bang; }
  11. CSS
  12. .foo {// bar: baz;}
  13. baz: bang; //}
  14. }
  15. SCSS
  16. assert_equal <<CSS, render(<<SCSS)
  17. .foo bar[val="//"] {
  18. baz: bang; }
  19. CSS
  20. .foo bar[val="//"] {
  21. baz: bang; //}
  22. }
  23. SCSS
  24. end
  25. ## Script
  26. def test_variables
  27. assert_equal <<CSS, render(<<SCSS)
  28. blat {
  29. a: foo; }
  30. CSS
  31. $var: foo;
  32. blat {a: $var}
  33. SCSS
  34. assert_equal <<CSS, render(<<SCSS)
  35. foo {
  36. a: 2;
  37. b: 6; }
  38. CSS
  39. foo {
  40. $var: 2;
  41. $another-var: 4;
  42. a: $var;
  43. b: $var + $another-var;}
  44. SCSS
  45. end
  46. def test_unicode_variables
  47. assert_equal <<CSS, render(<<SCSS)
  48. blat {
  49. a: foo; }
  50. CSS
  51. $vär: foo;
  52. blat {a: $vär}
  53. SCSS
  54. end
  55. def test_guard_assign
  56. assert_equal <<CSS, render(<<SCSS)
  57. foo {
  58. a: 1; }
  59. CSS
  60. $var: 1;
  61. $var: 2 !default;
  62. foo {a: $var}
  63. SCSS
  64. assert_equal <<CSS, render(<<SCSS)
  65. foo {
  66. a: 2; }
  67. CSS
  68. $var: 2 !default;
  69. foo {a: $var}
  70. SCSS
  71. end
  72. def test_sass_script
  73. assert_equal <<CSS, render(<<SCSS)
  74. foo {
  75. a: 3;
  76. b: -1;
  77. c: foobar;
  78. d: 12px; }
  79. CSS
  80. foo {
  81. a: 1 + 2;
  82. b: 1 - 2;
  83. c: foo + bar;
  84. d: floor(12.3px); }
  85. SCSS
  86. end
  87. def test_debug_directive
  88. assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
  89. assert_equal <<CSS, render(<<SCSS)
  90. foo {
  91. a: b; }
  92. bar {
  93. c: d; }
  94. CSS
  95. foo {a: b}
  96. @debug "hello world!";
  97. bar {c: d}
  98. SCSS
  99. end
  100. end
  101. def test_warn_directive
  102. expected_warning = <<EXPECTATION
  103. WARNING: this is a warning
  104. on line 2 of test_warn_directive_inline.scss
  105. WARNING: this is a mixin
  106. on line 1 of test_warn_directive_inline.scss, in `foo'
  107. from line 3 of test_warn_directive_inline.scss
  108. EXPECTATION
  109. assert_warning expected_warning do
  110. assert_equal <<CSS, render(<<SCSS)
  111. bar {
  112. c: d; }
  113. CSS
  114. @mixin foo { @warn "this is a mixin";}
  115. @warn "this is a warning";
  116. bar {c: d; @include foo;}
  117. SCSS
  118. end
  119. end
  120. def test_for_directive
  121. assert_equal <<CSS, render(<<SCSS)
  122. .foo {
  123. a: 1;
  124. a: 2;
  125. a: 3;
  126. a: 4; }
  127. CSS
  128. .foo {
  129. @for $var from 1 to 5 {a: $var;}
  130. }
  131. SCSS
  132. assert_equal <<CSS, render(<<SCSS)
  133. .foo {
  134. a: 1;
  135. a: 2;
  136. a: 3;
  137. a: 4;
  138. a: 5; }
  139. CSS
  140. .foo {
  141. @for $var from 1 through 5 {a: $var;}
  142. }
  143. SCSS
  144. end
  145. def test_if_directive
  146. assert_equal <<CSS, render(<<SCSS)
  147. foo {
  148. a: b; }
  149. CSS
  150. @if "foo" == "foo" {foo {a: b}}
  151. @if "foo" != "foo" {bar {a: b}}
  152. SCSS
  153. assert_equal <<CSS, render(<<SCSS)
  154. bar {
  155. a: b; }
  156. CSS
  157. @if "foo" != "foo" {foo {a: b}}
  158. @else if "foo" == "foo" {bar {a: b}}
  159. @else if true {baz {a: b}}
  160. SCSS
  161. assert_equal <<CSS, render(<<SCSS)
  162. bar {
  163. a: b; }
  164. CSS
  165. @if "foo" != "foo" {foo {a: b}}
  166. @else {bar {a: b}}
  167. SCSS
  168. end
  169. def test_comment_after_if_directive
  170. assert_equal <<CSS, render(<<SCSS)
  171. foo {
  172. a: b;
  173. /* This is a comment */
  174. c: d; }
  175. CSS
  176. foo {
  177. @if true {a: b}
  178. /* This is a comment */
  179. c: d }
  180. SCSS
  181. assert_equal <<CSS, render(<<SCSS)
  182. foo {
  183. a: b;
  184. /* This is a comment */
  185. c: d; }
  186. CSS
  187. foo {
  188. @if true {a: b}
  189. @else {x: y}
  190. /* This is a comment */
  191. c: d }
  192. SCSS
  193. end
  194. def test_while_directive
  195. assert_equal <<CSS, render(<<SCSS)
  196. .foo {
  197. a: 1;
  198. a: 2;
  199. a: 3;
  200. a: 4; }
  201. CSS
  202. $i: 1;
  203. .foo {
  204. @while $i != 5 {
  205. a: $i;
  206. $i: $i + 1;
  207. }
  208. }
  209. SCSS
  210. end
  211. def test_each_directive
  212. assert_equal <<CSS, render(<<SCSS)
  213. a {
  214. b: 1px;
  215. b: 2px;
  216. b: 3px;
  217. b: 4px; }
  218. c {
  219. d: foo;
  220. d: bar;
  221. d: baz;
  222. d: bang; }
  223. CSS
  224. a {
  225. @each $number in 1px 2px 3px 4px {
  226. b: $number;
  227. }
  228. }
  229. c {
  230. @each $str in foo, bar, baz, bang {
  231. d: $str;
  232. }
  233. }
  234. SCSS
  235. end
  236. def test_css_import_directive
  237. assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
  238. assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
  239. assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
  240. assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
  241. assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
  242. end
  243. def test_media_import
  244. assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
  245. end
  246. def test_dynamic_media_import
  247. assert_equal(<<CSS, render(<<SCSS))
  248. @import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
  249. CSS
  250. $media: print;
  251. $key: -webkit-min-device-pixel-ratio;
  252. $value: 20;
  253. @import "foo" \#{$media} and ($key + "-foo": $value + 5);
  254. SCSS
  255. end
  256. def test_http_import
  257. assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
  258. render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";"))
  259. end
  260. def test_protocol_relative_import
  261. assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
  262. render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";"))
  263. end
  264. def test_import_with_interpolation
  265. assert_equal <<CSS, render(<<SCSS)
  266. @import url("http://fonts.googleapis.com/css?family=Droid+Sans");
  267. CSS
  268. $family: unquote("Droid+Sans");
  269. @import url("http://fonts.googleapis.com/css?family=\#{$family}");
  270. SCSS
  271. end
  272. def test_url_import
  273. assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
  274. end
  275. def test_block_comment_in_script
  276. assert_equal <<CSS, render(<<SCSS)
  277. foo {
  278. a: 1bar; }
  279. CSS
  280. foo {a: 1 + /* flang */ bar}
  281. SCSS
  282. end
  283. def test_line_comment_in_script
  284. assert_equal <<CSS, render(<<SCSS)
  285. foo {
  286. a: 1blang; }
  287. CSS
  288. foo {a: 1 + // flang }
  289. blang }
  290. SCSS
  291. end
  292. ## Nested Rules
  293. def test_nested_rules
  294. assert_equal <<CSS, render(<<SCSS)
  295. foo bar {
  296. a: b; }
  297. CSS
  298. foo {bar {a: b}}
  299. SCSS
  300. assert_equal <<CSS, render(<<SCSS)
  301. foo bar {
  302. a: b; }
  303. foo baz {
  304. b: c; }
  305. CSS
  306. foo {
  307. bar {a: b}
  308. baz {b: c}}
  309. SCSS
  310. assert_equal <<CSS, render(<<SCSS)
  311. foo bar baz {
  312. a: b; }
  313. foo bang bip {
  314. a: b; }
  315. CSS
  316. foo {
  317. bar {baz {a: b}}
  318. bang {bip {a: b}}}
  319. SCSS
  320. end
  321. def test_nested_rules_with_declarations
  322. assert_equal <<CSS, render(<<SCSS)
  323. foo {
  324. a: b; }
  325. foo bar {
  326. c: d; }
  327. CSS
  328. foo {
  329. a: b;
  330. bar {c: d}}
  331. SCSS
  332. assert_equal <<CSS, render(<<SCSS)
  333. foo {
  334. a: b; }
  335. foo bar {
  336. c: d; }
  337. CSS
  338. foo {
  339. bar {c: d}
  340. a: b}
  341. SCSS
  342. assert_equal <<CSS, render(<<SCSS)
  343. foo {
  344. ump: nump;
  345. grump: clump; }
  346. foo bar {
  347. blat: bang;
  348. habit: rabbit; }
  349. foo bar baz {
  350. a: b; }
  351. foo bar bip {
  352. c: d; }
  353. foo bibble bap {
  354. e: f; }
  355. CSS
  356. foo {
  357. ump: nump;
  358. grump: clump;
  359. bar {
  360. blat: bang;
  361. habit: rabbit;
  362. baz {a: b}
  363. bip {c: d}}
  364. bibble {
  365. bap {e: f}}}
  366. SCSS
  367. end
  368. def test_nested_rules_with_fancy_selectors
  369. assert_equal <<CSS, render(<<SCSS)
  370. foo .bar {
  371. a: b; }
  372. foo :baz {
  373. c: d; }
  374. foo bang:bop {
  375. e: f; }
  376. CSS
  377. foo {
  378. .bar {a: b}
  379. :baz {c: d}
  380. bang:bop {e: f}}
  381. SCSS
  382. end
  383. def test_almost_ambiguous_nested_rules_and_declarations
  384. assert_equal <<CSS, render(<<SCSS)
  385. foo {
  386. bar: baz bang bop biddle woo look at all these elems; }
  387. foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
  388. a: b; }
  389. foo bar:baz bang bop biddle woo look at all these elems {
  390. a: b; }
  391. CSS
  392. foo {
  393. bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
  394. bar:baz bang bop biddle woo look at all these elems {a: b};
  395. bar:baz bang bop biddle woo look at all these elems; }
  396. SCSS
  397. end
  398. def test_newlines_in_selectors
  399. assert_equal <<CSS, render(<<SCSS)
  400. foo
  401. bar {
  402. a: b; }
  403. CSS
  404. foo
  405. bar {a: b}
  406. SCSS
  407. assert_equal <<CSS, render(<<SCSS)
  408. foo baz,
  409. foo bang,
  410. bar baz,
  411. bar bang {
  412. a: b; }
  413. CSS
  414. foo,
  415. bar {
  416. baz,
  417. bang {a: b}}
  418. SCSS
  419. assert_equal <<CSS, render(<<SCSS)
  420. foo
  421. bar baz
  422. bang {
  423. a: b; }
  424. foo
  425. bar bip bop {
  426. c: d; }
  427. CSS
  428. foo
  429. bar {
  430. baz
  431. bang {a: b}
  432. bip bop {c: d}}
  433. SCSS
  434. assert_equal <<CSS, render(<<SCSS)
  435. foo bang, foo bip
  436. bop, bar
  437. baz bang, bar
  438. baz bip
  439. bop {
  440. a: b; }
  441. CSS
  442. foo, bar
  443. baz {
  444. bang, bip
  445. bop {a: b}}
  446. SCSS
  447. end
  448. def test_trailing_comma_in_selector
  449. assert_equal <<CSS, render(<<SCSS)
  450. #foo #bar,
  451. #baz #boom {
  452. a: b; }
  453. #bip #bop {
  454. c: d; }
  455. CSS
  456. #foo #bar,,
  457. ,#baz #boom, {a: b}
  458. #bip #bop, ,, {c: d}
  459. SCSS
  460. end
  461. def test_parent_selectors
  462. assert_equal <<CSS, render(<<SCSS)
  463. foo:hover {
  464. a: b; }
  465. bar foo.baz {
  466. c: d; }
  467. CSS
  468. foo {
  469. &:hover {a: b}
  470. bar &.baz {c: d}}
  471. SCSS
  472. end
  473. def test_parent_selector_with_subject
  474. assert_equal <<CSS, render(<<SCSS)
  475. bar foo.baz! .bip {
  476. a: b; }
  477. bar foo bar.baz! .bip {
  478. c: d; }
  479. CSS
  480. foo {
  481. bar &.baz! .bip {a: b}}
  482. foo bar {
  483. bar &.baz! .bip {c: d}}
  484. SCSS
  485. end
  486. ## Namespace Properties
  487. def test_namespace_properties
  488. assert_equal <<CSS, render(<<SCSS)
  489. foo {
  490. bar: baz;
  491. bang-bip: 1px;
  492. bang-bop: bar; }
  493. CSS
  494. foo {
  495. bar: baz;
  496. bang: {
  497. bip: 1px;
  498. bop: bar;}}
  499. SCSS
  500. end
  501. def test_several_namespace_properties
  502. assert_equal <<CSS, render(<<SCSS)
  503. foo {
  504. bar: baz;
  505. bang-bip: 1px;
  506. bang-bop: bar;
  507. buzz-fram: "foo";
  508. buzz-frum: moo; }
  509. CSS
  510. foo {
  511. bar: baz;
  512. bang: {
  513. bip: 1px;
  514. bop: bar;}
  515. buzz: {
  516. fram: "foo";
  517. frum: moo;
  518. }
  519. }
  520. SCSS
  521. end
  522. def test_nested_namespace_properties
  523. assert_equal <<CSS, render(<<SCSS)
  524. foo {
  525. bar: baz;
  526. bang-bip: 1px;
  527. bang-bop: bar;
  528. bang-blat-baf: bort; }
  529. CSS
  530. foo {
  531. bar: baz;
  532. bang: {
  533. bip: 1px;
  534. bop: bar;
  535. blat:{baf:bort}}}
  536. SCSS
  537. end
  538. def test_namespace_properties_with_value
  539. assert_equal <<CSS, render(<<SCSS)
  540. foo {
  541. bar: baz;
  542. bar-bip: bop;
  543. bar-bing: bop; }
  544. CSS
  545. foo {
  546. bar: baz {
  547. bip: bop;
  548. bing: bop; }}
  549. SCSS
  550. end
  551. def test_namespace_properties_with_script_value
  552. assert_equal <<CSS, render(<<SCSS)
  553. foo {
  554. bar: bazbang;
  555. bar-bip: bop;
  556. bar-bing: bop; }
  557. CSS
  558. foo {
  559. bar: baz + bang {
  560. bip: bop;
  561. bing: bop; }}
  562. SCSS
  563. end
  564. def test_no_namespace_properties_without_space
  565. assert_equal <<CSS, render(<<SCSS)
  566. foo bar:baz {
  567. bip: bop; }
  568. CSS
  569. foo {
  570. bar:baz {
  571. bip: bop }}
  572. SCSS
  573. end
  574. def test_no_namespace_properties_without_space_even_when_its_unambiguous
  575. render(<<SCSS)
  576. foo {
  577. bar:1px {
  578. bip: bop }}
  579. SCSS
  580. assert(false, "Expected syntax error")
  581. rescue Sass::SyntaxError => e
  582. assert_equal <<MESSAGE, e.message
  583. Invalid CSS: a space is required between a property and its definition
  584. when it has other properties nested beneath it.
  585. MESSAGE
  586. assert_equal 2, e.sass_line
  587. end
  588. ## Mixins
  589. def test_basic_mixins
  590. assert_equal <<CSS, render(<<SCSS)
  591. .foo {
  592. a: b; }
  593. CSS
  594. @mixin foo {
  595. .foo {a: b}}
  596. @include foo;
  597. SCSS
  598. assert_equal <<CSS, render(<<SCSS)
  599. bar {
  600. c: d; }
  601. bar .foo {
  602. a: b; }
  603. CSS
  604. @mixin foo {
  605. .foo {a: b}}
  606. bar {
  607. @include foo;
  608. c: d; }
  609. SCSS
  610. assert_equal <<CSS, render(<<SCSS)
  611. bar {
  612. a: b;
  613. c: d; }
  614. CSS
  615. @mixin foo {a: b}
  616. bar {
  617. @include foo;
  618. c: d; }
  619. SCSS
  620. end
  621. def test_mixins_with_empty_args
  622. assert_equal <<CSS, render(<<SCSS)
  623. .foo {
  624. a: b; }
  625. CSS
  626. @mixin foo() {a: b}
  627. .foo {@include foo();}
  628. SCSS
  629. assert_equal <<CSS, render(<<SCSS)
  630. .foo {
  631. a: b; }
  632. CSS
  633. @mixin foo() {a: b}
  634. .foo {@include foo;}
  635. SCSS
  636. assert_equal <<CSS, render(<<SCSS)
  637. .foo {
  638. a: b; }
  639. CSS
  640. @mixin foo {a: b}
  641. .foo {@include foo();}
  642. SCSS
  643. end
  644. def test_mixins_with_args
  645. assert_equal <<CSS, render(<<SCSS)
  646. .foo {
  647. a: bar; }
  648. CSS
  649. @mixin foo($a) {a: $a}
  650. .foo {@include foo(bar)}
  651. SCSS
  652. assert_equal <<CSS, render(<<SCSS)
  653. .foo {
  654. a: bar;
  655. b: 12px; }
  656. CSS
  657. @mixin foo($a, $b) {
  658. a: $a;
  659. b: $b; }
  660. .foo {@include foo(bar, 12px)}
  661. SCSS
  662. end
  663. ## Functions
  664. def test_basic_function
  665. assert_equal(<<CSS, render(<<SASS))
  666. bar {
  667. a: 3; }
  668. CSS
  669. @function foo() {
  670. @return 1 + 2;
  671. }
  672. bar {
  673. a: foo();
  674. }
  675. SASS
  676. end
  677. def test_function_args
  678. assert_equal(<<CSS, render(<<SASS))
  679. bar {
  680. a: 3; }
  681. CSS
  682. @function plus($var1, $var2) {
  683. @return $var1 + $var2;
  684. }
  685. bar {
  686. a: plus(1, 2);
  687. }
  688. SASS
  689. end
  690. ## Var Args
  691. def test_mixin_var_args
  692. assert_equal <<CSS, render(<<SCSS)
  693. .foo {
  694. a: 1;
  695. b: 2, 3, 4; }
  696. CSS
  697. @mixin foo($a, $b...) {
  698. a: $a;
  699. b: $b;
  700. }
  701. .foo {@include foo(1, 2, 3, 4)}
  702. SCSS
  703. end
  704. def test_mixin_empty_var_args
  705. assert_equal <<CSS, render(<<SCSS)
  706. .foo {
  707. a: 1;
  708. b: 0; }
  709. CSS
  710. @mixin foo($a, $b...) {
  711. a: $a;
  712. b: length($b);
  713. }
  714. .foo {@include foo(1)}
  715. SCSS
  716. end
  717. def test_mixin_var_args_act_like_list
  718. assert_equal <<CSS, render(<<SCSS)
  719. .foo {
  720. a: 3;
  721. b: 3; }
  722. CSS
  723. @mixin foo($a, $b...) {
  724. a: length($b);
  725. b: nth($b, 2);
  726. }
  727. .foo {@include foo(1, 2, 3, 4)}
  728. SCSS
  729. end
  730. def test_mixin_splat_args
  731. assert_equal <<CSS, render(<<SCSS)
  732. .foo {
  733. a: 1;
  734. b: 2;
  735. c: 3;
  736. d: 4; }
  737. CSS
  738. @mixin foo($a, $b, $c, $d) {
  739. a: $a;
  740. b: $b;
  741. c: $c;
  742. d: $d;
  743. }
  744. $list: 2, 3, 4;
  745. .foo {@include foo(1, $list...)}
  746. SCSS
  747. end
  748. def test_mixin_splat_expression
  749. assert_equal <<CSS, render(<<SCSS)
  750. .foo {
  751. a: 1;
  752. b: 2;
  753. c: 3;
  754. d: 4; }
  755. CSS
  756. @mixin foo($a, $b, $c, $d) {
  757. a: $a;
  758. b: $b;
  759. c: $c;
  760. d: $d;
  761. }
  762. .foo {@include foo(1, (2, 3, 4)...)}
  763. SCSS
  764. end
  765. def test_mixin_splat_args_with_var_args
  766. assert_equal <<CSS, render(<<SCSS)
  767. .foo {
  768. a: 1;
  769. b: 2, 3, 4; }
  770. CSS
  771. @mixin foo($a, $b...) {
  772. a: $a;
  773. b: $b;
  774. }
  775. $list: 2, 3, 4;
  776. .foo {@include foo(1, $list...)}
  777. SCSS
  778. end
  779. def test_mixin_splat_args_with_var_args_and_normal_args
  780. assert_equal <<CSS, render(<<SCSS)
  781. .foo {
  782. a: 1;
  783. b: 2;
  784. c: 3, 4; }
  785. CSS
  786. @mixin foo($a, $b, $c...) {
  787. a: $a;
  788. b: $b;
  789. c: $c;
  790. }
  791. $list: 2, 3, 4;
  792. .foo {@include foo(1, $list...)}
  793. SCSS
  794. end
  795. def test_mixin_splat_args_with_var_args_preserves_separator
  796. assert_equal <<CSS, render(<<SCSS)
  797. .foo {
  798. a: 1;
  799. b: 2 3 4 5; }
  800. CSS
  801. @mixin foo($a, $b...) {
  802. a: $a;
  803. b: $b;
  804. }
  805. $list: 3 4 5;
  806. .foo {@include foo(1, 2, $list...)}
  807. SCSS
  808. end
  809. def test_mixin_var_and_splat_args_pass_through_keywords
  810. assert_equal <<CSS, render(<<SCSS)
  811. .foo {
  812. a: 3;
  813. b: 1;
  814. c: 2; }
  815. CSS
  816. @mixin foo($a...) {
  817. @include bar($a...);
  818. }
  819. @mixin bar($b, $c, $a) {
  820. a: $a;
  821. b: $b;
  822. c: $c;
  823. }
  824. .foo {@include foo(1, $c: 2, $a: 3)}
  825. SCSS
  826. end
  827. def test_mixin_var_args_with_keyword
  828. assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
  829. @mixin foo($a, $b...) {
  830. a: $a;
  831. b: $b;
  832. }
  833. .foo {@include foo($a: 1, 2, 3, 4)}
  834. SCSS
  835. end
  836. def test_mixin_keyword_for_var_arg
  837. assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
  838. @mixin foo($a, $b...) {
  839. a: $a;
  840. b: $b;
  841. }
  842. .foo {@include foo(1, $b: 2 3 4)}
  843. SCSS
  844. end
  845. def test_mixin_keyword_for_unknown_arg_with_var_args
  846. assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
  847. @mixin foo($a, $b...) {
  848. a: $a;
  849. b: $b;
  850. }
  851. .foo {@include foo(1, $c: 2 3 4)}
  852. SCSS
  853. end
  854. def test_function_var_args
  855. assert_equal <<CSS, render(<<SCSS)
  856. .foo {
  857. val: "a: 1, b: 2, 3, 4"; }
  858. CSS
  859. @function foo($a, $b...) {
  860. @return "a: \#{$a}, b: \#{$b}";
  861. }
  862. .foo {val: foo(1, 2, 3, 4)}
  863. SCSS
  864. end
  865. def test_function_empty_var_args
  866. assert_equal <<CSS, render(<<SCSS)
  867. .foo {
  868. val: "a: 1, b: 0"; }
  869. CSS
  870. @function foo($a, $b...) {
  871. @return "a: \#{$a}, b: \#{length($b)}";
  872. }
  873. .foo {val: foo(1)}
  874. SCSS
  875. end
  876. def test_function_var_args_act_like_list
  877. assert_equal <<CSS, render(<<SCSS)
  878. .foo {
  879. val: "a: 3, b: 3"; }
  880. CSS
  881. @function foo($a, $b...) {
  882. @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
  883. }
  884. .foo {val: foo(1, 2, 3, 4)}
  885. SCSS
  886. end
  887. def test_function_splat_args
  888. assert_equal <<CSS, render(<<SCSS)
  889. .foo {
  890. val: "a: 1, b: 2, c: 3, d: 4"; }
  891. CSS
  892. @function foo($a, $b, $c, $d) {
  893. @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
  894. }
  895. $list: 2, 3, 4;
  896. .foo {val: foo(1, $list...)}
  897. SCSS
  898. end
  899. def test_function_splat_expression
  900. assert_equal <<CSS, render(<<SCSS)
  901. .foo {
  902. val: "a: 1, b: 2, c: 3, d: 4"; }
  903. CSS
  904. @function foo($a, $b, $c, $d) {
  905. @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
  906. }
  907. .foo {val: foo(1, (2, 3, 4)...)}
  908. SCSS
  909. end
  910. def test_function_splat_args_with_var_args
  911. assert_equal <<CSS, render(<<SCSS)
  912. .foo {
  913. val: "a: 1, b: 2, 3, 4"; }
  914. CSS
  915. @function foo($a, $b...) {
  916. @return "a: \#{$a}, b: \#{$b}";
  917. }
  918. $list: 2, 3, 4;
  919. .foo {val: foo(1, $list...)}
  920. SCSS
  921. end
  922. def test_function_splat_args_with_var_args_and_normal_args
  923. assert_equal <<CSS, render(<<SCSS)
  924. .foo {
  925. val: "a: 1, b: 2, c: 3, 4"; }
  926. CSS
  927. @function foo($a, $b, $c...) {
  928. @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
  929. }
  930. $list: 2, 3, 4;
  931. .foo {val: foo(1, $list...)}
  932. SCSS
  933. end
  934. def test_function_splat_args_with_var_args_preserves_separator
  935. assert_equal <<CSS, render(<<SCSS)
  936. .foo {
  937. val: "a: 1, b: 2 3 4 5"; }
  938. CSS
  939. @function foo($a, $b...) {
  940. @return "a: \#{$a}, b: \#{$b}";
  941. }
  942. $list: 3 4 5;
  943. .foo {val: foo(1, 2, $list...)}
  944. SCSS
  945. end
  946. def test_function_var_and_splat_args_pass_through_keywords
  947. assert_equal <<CSS, render(<<SCSS)
  948. .foo {
  949. val: "a: 3, b: 1, c: 2"; }
  950. CSS
  951. @function foo($a...) {
  952. @return bar($a...);
  953. }
  954. @function bar($b, $c, $a) {
  955. @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
  956. }
  957. .foo {val: foo(1, $c: 2, $a: 3)}
  958. SCSS
  959. end
  960. def test_function_var_args_with_keyword
  961. assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
  962. @function foo($a, $b...) {
  963. @return "a: \#{$a}, b: $b";
  964. }
  965. .foo {val: foo($a: 1, 2, 3, 4)}
  966. SCSS
  967. end
  968. def test_function_keyword_for_var_arg
  969. assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
  970. @function foo($a, $b...) {
  971. @return "a: \#{$a}, b: \#{$b}";
  972. }
  973. .foo {val: foo(1, $b: 2 3 4)}
  974. SCSS
  975. end
  976. def test_function_keyword_for_unknown_arg_with_var_args
  977. assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
  978. @function foo($a, $b...) {
  979. @return "a: \#{$a}, b: \#{$b}";
  980. }
  981. .foo {val: foo(1, $c: 2 3 4)}
  982. SCSS
  983. end
  984. def test_function_var_args_passed_to_native
  985. assert_equal <<CSS, render(<<SCSS)
  986. .foo {
  987. val: #102035; }
  988. CSS
  989. @function foo($args...) {
  990. @return adjust-color($args...);
  991. }
  992. .foo {val: foo(#102030, $blue: 5)}
  993. SCSS
  994. end
  995. ## Interpolation
  996. def test_basic_selector_interpolation
  997. assert_equal <<CSS, render(<<SCSS)
  998. foo 3 baz {
  999. a: b; }
  1000. CSS
  1001. foo \#{1 + 2} baz {a: b}
  1002. SCSS
  1003. assert_equal <<CSS, render(<<SCSS)
  1004. foo.bar baz {
  1005. a: b; }
  1006. CSS
  1007. foo\#{".bar"} baz {a: b}
  1008. SCSS
  1009. assert_equal <<CSS, render(<<SCSS)
  1010. foo.bar baz {
  1011. a: b; }
  1012. CSS
  1013. \#{"foo"}.bar baz {a: b}
  1014. SCSS
  1015. end
  1016. def test_selector_only_interpolation
  1017. assert_equal <<CSS, render(<<SCSS)
  1018. foo bar {
  1019. a: b; }
  1020. CSS
  1021. \#{"foo" + " bar"} {a: b}
  1022. SCSS
  1023. end
  1024. def test_selector_interpolation_before_element_name
  1025. assert_equal <<CSS, render(<<SCSS)
  1026. foo barbaz {
  1027. a: b; }
  1028. CSS
  1029. \#{"foo" + " bar"}baz {a: b}
  1030. SCSS
  1031. end
  1032. def test_selector_interpolation_in_string
  1033. assert_equal <<CSS, render(<<SCSS)
  1034. foo[val="bar foo bar baz"] {
  1035. a: b; }
  1036. CSS
  1037. foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
  1038. SCSS
  1039. end
  1040. def test_selector_interpolation_in_pseudoclass
  1041. assert_equal <<CSS, render(<<SCSS)
  1042. foo:nth-child(5n) {
  1043. a: b; }
  1044. CSS
  1045. foo:nth-child(\#{5 + "n"}) {a: b}
  1046. SCSS
  1047. end
  1048. def test_selector_interpolation_at_class_begininng
  1049. assert_equal <<CSS, render(<<SCSS)
  1050. .zzz {
  1051. a: b; }
  1052. CSS
  1053. $zzz: zzz;
  1054. .\#{$zzz} { a: b; }
  1055. SCSS
  1056. end
  1057. def test_selector_interpolation_at_id_begininng
  1058. assert_equal <<CSS, render(<<SCSS)
  1059. #zzz {
  1060. a: b; }
  1061. CSS
  1062. $zzz: zzz;
  1063. #\#{$zzz} { a: b; }
  1064. SCSS
  1065. end
  1066. def test_selector_interpolation_at_pseudo_begininng
  1067. assert_equal <<CSS, render(<<SCSS)
  1068. :zzz::zzz {
  1069. a: b; }
  1070. CSS
  1071. $zzz: zzz;
  1072. :\#{$zzz}::\#{$zzz} { a: b; }
  1073. SCSS
  1074. end
  1075. def test_selector_interpolation_at_attr_beginning
  1076. assert_equal <<CSS, render(<<SCSS)
  1077. [zzz=foo] {
  1078. a: b; }
  1079. CSS
  1080. $zzz: zzz;
  1081. [\#{$zzz}=foo] { a: b; }
  1082. SCSS
  1083. end
  1084. def test_selector_interpolation_at_attr_end
  1085. assert_equal <<CSS, render(<<SCSS)
  1086. [foo=zzz] {
  1087. a: b; }
  1088. CSS
  1089. $zzz: zzz;
  1090. [foo=\#{$zzz}] { a: b; }
  1091. SCSS
  1092. end
  1093. def test_selector_interpolation_at_dashes
  1094. assert_equal <<CSS, render(<<SCSS)
  1095. div {
  1096. -foo-a-b-foo: foo; }
  1097. CSS
  1098. $a : a;
  1099. $b : b;
  1100. div { -foo-\#{$a}-\#{$b}-foo: foo }
  1101. SCSS
  1102. end
  1103. def test_selector_interpolation_in_reference_combinator
  1104. assert_equal <<CSS, render(<<SCSS)
  1105. .foo /a/ .bar /b|c/ .baz {
  1106. a: b; }
  1107. CSS
  1108. $a: a;
  1109. $b: b;
  1110. $c: c;
  1111. .foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
  1112. SCSS
  1113. end
  1114. def test_parent_selector_with_parent_and_subject
  1115. assert_equal <<CSS, render(<<SCSS)
  1116. bar foo.baz! .bip {
  1117. c: d; }
  1118. CSS
  1119. $subject: "!";
  1120. foo {
  1121. bar &.baz\#{$subject} .bip {c: d}}
  1122. SCSS
  1123. end
  1124. def test_basic_prop_name_interpolation
  1125. assert_equal <<CSS, render(<<SCSS)
  1126. foo {
  1127. barbazbang: blip; }
  1128. CSS
  1129. foo {bar\#{"baz" + "bang"}: blip}
  1130. SCSS
  1131. assert_equal <<CSS, render(<<SCSS)
  1132. foo {
  1133. bar3: blip; }
  1134. CSS
  1135. foo {bar\#{1 + 2}: blip}
  1136. SCSS
  1137. end
  1138. def test_prop_name_only_interpolation
  1139. assert_equal <<CSS, render(<<SCSS)
  1140. foo {
  1141. bazbang: blip; }
  1142. CSS
  1143. foo {\#{"baz" + "bang"}: blip}
  1144. SCSS
  1145. end
  1146. def test_directive_interpolation
  1147. assert_equal <<CSS, render(<<SCSS)
  1148. @foo bar12 qux {
  1149. a: b; }
  1150. CSS
  1151. $baz: 12;
  1152. @foo bar\#{$baz} qux {a: b}
  1153. SCSS
  1154. end
  1155. def test_media_interpolation
  1156. assert_equal <<CSS, render(<<SCSS)
  1157. @media bar12 {
  1158. a: b; }
  1159. CSS
  1160. $baz: 12;
  1161. @media bar\#{$baz} {a: b}
  1162. SCSS
  1163. end
  1164. def test_script_in_media
  1165. assert_equal <<CSS, render(<<SCSS)
  1166. @media screen and (-webkit-min-device-pixel-ratio: 20), only print {
  1167. a: b; }
  1168. CSS
  1169. $media1: screen;
  1170. $media2: print;
  1171. $var: -webkit-min-device-pixel-ratio;
  1172. $val: 20;
  1173. @media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
  1174. SCSS
  1175. assert_equal <<CSS, render(<<SCSS)
  1176. @media screen and (-webkit-min-device-pixel-ratio: 13) {
  1177. a: b; }
  1178. CSS
  1179. $vals: 1 2 3;
  1180. @media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
  1181. SCSS
  1182. end
  1183. def test_media_interpolation_with_reparse
  1184. assert_equal <<CSS, render(<<SCSS)
  1185. @media screen and (max-width: 300px) {
  1186. a: b; }
  1187. @media screen and (max-width: 300px) {
  1188. a: b; }
  1189. @media screen and (max-width: 300px) {
  1190. a: b; }
  1191. @media screen and (max-width: 300px), print and (max-width: 300px) {
  1192. a: b; }
  1193. CSS
  1194. $constraint: "(max-width: 300px)";
  1195. $fragment: "nd \#{$constraint}";
  1196. $comma: "een, pri";
  1197. @media screen and \#{$constraint} {a: b}
  1198. @media screen {
  1199. @media \#{$constraint} {a: b}
  1200. }
  1201. @media screen a\#{$fragment} {a: b}
  1202. @media scr\#{$comma}nt {
  1203. @media \#{$constraint} {a: b}
  1204. }
  1205. SCSS
  1206. end
  1207. def test_moz_document_interpolation
  1208. assert_equal <<CSS, render(<<SCSS)
  1209. @-moz-document url(http://sass-lang.com/),
  1210. url-prefix(http://sass-lang.com/docs),
  1211. domain(sass-lang.com),
  1212. domain("sass-lang.com") {
  1213. .foo {
  1214. a: b; } }
  1215. CSS
  1216. $domain: "sass-lang.com";
  1217. @-moz-document url(http://\#{$domain}/),
  1218. url-prefix(http://\#{$domain}/docs),
  1219. domain(\#{$domain}),
  1220. \#{domain($domain)} {
  1221. .foo {a: b}
  1222. }
  1223. SCSS
  1224. end
  1225. def test_supports_with_expressions
  1226. assert_equal <<CSS, render(<<SCSS)
  1227. @supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
  1228. foo {
  1229. a: b; } }
  1230. CSS
  1231. $query: "(feature1: val)";
  1232. $feature: feature2;
  1233. $val: val;
  1234. @supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
  1235. foo {a: b}
  1236. }
  1237. SCSS
  1238. end
  1239. def test_supports_bubbling
  1240. assert_equal <<CSS, render(<<SCSS)
  1241. @supports (foo: bar) {
  1242. a {
  1243. b: c; }
  1244. @supports (baz: bang) {
  1245. a {
  1246. d: e; } } }
  1247. CSS
  1248. a {
  1249. @supports (foo: bar) {
  1250. b: c;
  1251. @supports (baz: bang) {
  1252. d: e;
  1253. }
  1254. }
  1255. }
  1256. SCSS
  1257. end
  1258. def test_random_directive_interpolation
  1259. assert_equal <<CSS, render(<<SCSS)
  1260. @foo url(http://sass-lang.com/),
  1261. domain("sass-lang.com"),
  1262. "foobarbaz",
  1263. foobarbaz {
  1264. .foo {
  1265. a: b; } }
  1266. CSS
  1267. $domain: "sass-lang.com";
  1268. @foo url(http://\#{$domain}/),
  1269. \#{domain($domain)},
  1270. "foo\#{'ba' + 'r'}baz",
  1271. foo\#{'ba' + 'r'}baz {
  1272. .foo {a: b}
  1273. }
  1274. SCSS
  1275. end
  1276. def test_nested_mixin_def
  1277. assert_equal <<CSS, render(<<SCSS)
  1278. foo {
  1279. a: b; }
  1280. CSS
  1281. foo {
  1282. @mixin bar {a: b}
  1283. @include bar; }
  1284. SCSS
  1285. end
  1286. def test_nested_mixin_shadow
  1287. assert_equal <<CSS, render(<<SCSS)
  1288. foo {
  1289. c: d; }
  1290. baz {
  1291. a: b; }
  1292. CSS
  1293. @mixin bar {a: b}
  1294. foo {
  1295. @mixin bar {c: d}
  1296. @include bar;
  1297. }
  1298. baz {@include bar}
  1299. SCSS
  1300. end
  1301. def test_nested_function_def
  1302. assert_equal <<CSS, render(<<SCSS)
  1303. foo {
  1304. a: 1; }
  1305. bar {
  1306. b: foo(); }
  1307. CSS
  1308. foo {
  1309. @function foo() {@return 1}
  1310. a: foo(); }
  1311. bar {b: foo()}
  1312. SCSS
  1313. end
  1314. def test_nested_function_shadow
  1315. assert_equal <<CSS, render(<<SCSS)
  1316. foo {
  1317. a: 2; }
  1318. baz {
  1319. b: 1; }
  1320. CSS
  1321. @function foo() {@return 1}
  1322. foo {
  1323. @function foo() {@return 2}
  1324. a: foo();
  1325. }
  1326. baz {b: foo()}
  1327. SCSS
  1328. end
  1329. ## Errors
  1330. def test_nested_mixin_def_is_scoped
  1331. render <<SCSS
  1332. foo {
  1333. @mixin bar {a: b}}
  1334. bar {@include bar}
  1335. SCSS
  1336. assert(false, "Expected syntax error")
  1337. rescue Sass::SyntaxError => e
  1338. assert_equal "Undefined mixin 'bar'.", e.message
  1339. assert_equal 3, e.sass_line
  1340. end
  1341. def test_rules_beneath_properties
  1342. render <<SCSS
  1343. foo {
  1344. bar: {
  1345. baz {
  1346. bang: bop }}}
  1347. SCSS
  1348. assert(false, "Expected syntax error")
  1349. rescue Sass::SyntaxError => e
  1350. assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
  1351. assert_equal 3, e.sass_line
  1352. end
  1353. def test_uses_property_exception_with_star_hack
  1354. render <<SCSS
  1355. foo {
  1356. *bar:baz [fail]; }
  1357. SCSS
  1358. assert(false, "Expected syntax error")
  1359. rescue Sass::SyntaxError => e
  1360. assert_equal 'Invalid CSS after " *bar:baz ": expected ";", was "[fail]; }"', e.message
  1361. assert_equal 2, e.sass_line
  1362. end
  1363. def test_uses_property_exception_with_colon_hack
  1364. render <<SCSS
  1365. foo {
  1366. :bar:baz [fail]; }
  1367. SCSS
  1368. assert(false, "Expected syntax error")
  1369. rescue Sass::SyntaxError => e
  1370. assert_equal 'Invalid CSS after " :bar:baz ": expected ";", was "[fail]; }"', e.message
  1371. assert_equal 2, e.sass_line
  1372. end
  1373. def test_uses_rule_exception_with_dot_hack
  1374. render <<SCSS
  1375. foo {
  1376. .bar:baz <fail>; }
  1377. SCSS
  1378. assert(false, "Expected syntax error")
  1379. rescue Sass::SyntaxError => e
  1380. assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "<fail>; }"', e.message
  1381. assert_equal 2, e.sass_line
  1382. end
  1383. def test_uses_property_exception_with_space_after_name
  1384. render <<SCSS
  1385. foo {
  1386. bar: baz [fail]; }
  1387. SCSS
  1388. assert(false, "Expected syntax error")
  1389. rescue Sass::SyntaxError => e
  1390. assert_equal 'Invalid CSS after " bar: baz ": expected ";", was "[fail]; }"', e.message
  1391. assert_equal 2, e.sass_line
  1392. end
  1393. def test_uses_property_exception_with_non_identifier_after_name
  1394. render <<SCSS
  1395. foo {
  1396. bar:1px [fail]; }
  1397. SCSS
  1398. assert(false, "Expected syntax error")
  1399. rescue Sass::SyntaxError => e
  1400. assert_equal 'Invalid CSS after " bar:1px ": expected ";", was "[fail]; }"', e.message
  1401. assert_equal 2, e.sass_line
  1402. end
  1403. def test_uses_property_exception_when_followed_by_open_bracket
  1404. render <<SCSS
  1405. foo {
  1406. bar:{baz: .fail} }
  1407. SCSS
  1408. assert(false, "Expected syntax error")
  1409. rescue Sass::SyntaxError => e
  1410. assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message
  1411. assert_equal 2, e.sass_line
  1412. end
  1413. def test_script_error
  1414. render <<SCSS
  1415. foo {
  1416. bar: "baz" * * }
  1417. SCSS
  1418. assert(false, "Expected syntax error")
  1419. rescue Sass::SyntaxError => e
  1420. assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
  1421. assert_equal 2, e.sass_line
  1422. end
  1423. def test_multiline_script_syntax_error
  1424. render <<SCSS
  1425. foo {
  1426. bar:
  1427. "baz" * * }
  1428. SCSS
  1429. assert(false, "Expected syntax error")
  1430. rescue Sass::SyntaxError => e
  1431. assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
  1432. assert_equal 3, e.sass_line
  1433. end
  1434. def test_multiline_script_runtime_error
  1435. render <<SCSS
  1436. foo {
  1437. bar: "baz" +
  1438. "bar" +
  1439. $bang }
  1440. SCSS
  1441. assert(false, "Expected syntax error")
  1442. rescue Sass::SyntaxError => e
  1443. assert_equal "Undefined variable: \"$bang\".", e.message
  1444. assert_equal 4, e.sass_line
  1445. end
  1446. def test_post_multiline_script_runtime_error
  1447. render <<SCSS
  1448. foo {
  1449. bar: "baz" +
  1450. "bar" +
  1451. "baz";
  1452. bip: $bop; }
  1453. SCSS
  1454. assert(false, "Expected syntax error")
  1455. rescue Sass::SyntaxError => e
  1456. assert_equal "Undefined variable: \"$bop\".", e.message
  1457. assert_equal 5, e.sass_line
  1458. end
  1459. def test_multiline_property_runtime_error
  1460. render <<SCSS
  1461. foo {
  1462. bar: baz
  1463. bar
  1464. \#{$bang} }
  1465. SCSS
  1466. assert(false, "Expected syntax error")
  1467. rescue Sass::SyntaxError => e
  1468. assert_equal "Undefined variable: \"$bang\".", e.message
  1469. assert_equal 4, e.sass_line
  1470. end
  1471. def test_post_resolution_selector_error
  1472. render "\n\nfoo \#{\") bar\"} {a: b}"
  1473. assert(false, "Expected syntax error")
  1474. rescue Sass::SyntaxError => e
  1475. assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message
  1476. assert_equal 3, e.sass_line
  1477. end
  1478. def test_parent_in_mid_selector_error
  1479. assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
  1480. Invalid CSS after " .foo": expected "{", was "&.bar {a: b}"
  1481. "&.bar" may only be used at the beginning of a compound selector.
  1482. MESSAGE
  1483. flim {
  1484. .foo&.bar {a: b}
  1485. }
  1486. SCSS
  1487. end
  1488. def test_parent_after_selector_error
  1489. assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
  1490. Invalid CSS after " .foo.bar": expected "{", was "& {a: b}"
  1491. "&" may only be used at the beginning of a compound selector.
  1492. MESSAGE
  1493. flim {
  1494. .foo.bar& {a: b}
  1495. }
  1496. SCSS
  1497. end
  1498. def test_double_parent_selector_error
  1499. assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
  1500. Invalid CSS after " &": expected "{", was "& {a: b}"
  1501. "&" may only be used at the beginning of a compound selector.
  1502. MESSAGE
  1503. flim {
  1504. && {a: b}
  1505. }
  1506. SCSS
  1507. end
  1508. def test_no_lonely_else
  1509. assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
  1510. Invalid CSS: @else must come after @if
  1511. MESSAGE
  1512. @else {foo: bar}
  1513. SCSS
  1514. end
  1515. # Regression
  1516. def test_parsing_decimals_followed_by_comments_doesnt_take_forever
  1517. assert_equal(<<CSS, render(<<SCSS))
  1518. .foo {
  1519. padding: 4.21053% 4.21053% 5.63158%; }
  1520. CSS
  1521. .foo {
  1522. padding: 4.21052631578947% 4.21052631578947% 5.631578947368421% /**/
  1523. }
  1524. SCSS
  1525. end
  1526. def test_parsing_many_numbers_doesnt_take_forever
  1527. values = ["80% 90%"] * 1000
  1528. assert_equal(<<CSS, render(<<SCSS))
  1529. .foo {
  1530. padding: #{values.join(', ')}; }
  1531. CSS
  1532. .foo {
  1533. padding: #{values.join(', ')};
  1534. }
  1535. SCSS
  1536. end
  1537. def test_import_comments_in_imports
  1538. assert_equal(<<CSS, render(<<SCSS))
  1539. @import url(foo.css);
  1540. @import url(bar.css);
  1541. @import url(baz.css);
  1542. CSS
  1543. @import "foo.css", // this is a comment
  1544. "bar.css", /* this is another comment */
  1545. "baz.css"; // this is a third comment
  1546. SCSS
  1547. end
  1548. def test_reference_combinator_with_parent_ref
  1549. assert_equal <<CSS, render(<<SCSS)
  1550. a /foo/ b {
  1551. c: d; }
  1552. CSS
  1553. a {& /foo/ b {c: d}}
  1554. SCSS
  1555. end
  1556. def test_newline_selector_rendered_multiple_times
  1557. assert_equal <<CSS, render(<<SCSS)
  1558. form input,
  1559. form select {
  1560. color: white; }
  1561. form input,
  1562. form select {
  1563. color: white; }
  1564. CSS
  1565. @for $i from 1 through 2 {
  1566. form {
  1567. input,
  1568. select {
  1569. color: white;
  1570. }
  1571. }
  1572. }
  1573. SCSS
  1574. end
  1575. def test_prop_name_interpolation_after_hyphen
  1576. assert_equal <<CSS, render(<<SCSS)
  1577. a {
  1578. -foo-bar: b; }
  1579. CSS
  1580. a { -\#{"foo"}-bar: b; }
  1581. SCSS
  1582. end
  1583. def test_star_plus_and_parent
  1584. assert_equal <<CSS, render(<<SCSS)
  1585. * + html foo {
  1586. a: b; }
  1587. CSS
  1588. foo {*+html & {a: b}}
  1589. SCSS
  1590. end
  1591. def test_weird_added_space
  1592. assert_equal <<CSS, render(<<SCSS)
  1593. foo {
  1594. bar: -moz-bip; }
  1595. CSS
  1596. $value : bip;
  1597. foo {
  1598. bar: -moz-\#{$value};
  1599. }
  1600. SCSS
  1601. end
  1602. def test_interpolation_with_bracket_on_next_line
  1603. assert_equal <<CSS, render(<<SCSS)
  1604. a.foo b {
  1605. color: red; }
  1606. CSS
  1607. a.\#{"foo"} b
  1608. {color: red}
  1609. SCSS
  1610. end
  1611. def test_extra_comma_in_mixin_arglist_error
  1612. assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
  1613. Invalid CSS after "...clude foo(bar, ": expected mixin argument, was ");"
  1614. MESSAGE
  1615. @mixin foo($a1, $a2) {
  1616. baz: $a1 $a2;
  1617. }
  1618. .bar {
  1619. @include foo(bar, );
  1620. }
  1621. SCSS
  1622. end
  1623. def test_interpolation
  1624. assert_equal <<CSS, render(<<SCSS)
  1625. ul li#foo a span.label {
  1626. foo: bar; }
  1627. CSS
  1628. $bar : "#foo";
  1629. ul li\#{$bar} a span.label { foo: bar; }
  1630. SCSS
  1631. end
  1632. def test_mixin_with_keyword_args
  1633. assert_equal <<CSS, render(<<SCSS)
  1634. .mixed {
  1635. required: foo;
  1636. arg1: default-val1;
  1637. arg2: non-default-val2; }
  1638. CSS
  1639. @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
  1640. required: $required;
  1641. arg1: $arg1;
  1642. arg2: $arg2;
  1643. }
  1644. .mixed { @include a-mixin(foo, $arg2: non-default-val2); }
  1645. SCSS
  1646. end
  1647. def test_passing_required_args_as_a_keyword_arg
  1648. assert_equal <<CSS, render(<<SCSS)
  1649. .mixed {
  1650. required: foo;
  1651. arg1: default-val1;
  1652. arg2: default-val2; }
  1653. CSS
  1654. @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
  1655. required: $required;
  1656. arg1: $arg1;
  1657. arg2: $arg2; }
  1658. .mixed { @include a-mixin($required: foo); }
  1659. SCSS
  1660. end
  1661. def test_passing_all_as_keyword_args_in_opposite_order
  1662. assert_equal <<CSS, render(<<SCSS)
  1663. .mixed {
  1664. required: foo;
  1665. arg1: non-default-val1;
  1666. arg2: non-default-val2; }
  1667. CSS
  1668. @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
  1669. required: $required;
  1670. arg1: $arg1;
  1671. arg2: $arg2; }
  1672. .mixed { @include a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo); }
  1673. SCSS
  1674. end
  1675. def test_keyword_args_in_functions
  1676. assert_equal <<CSS, render(<<SCSS)
  1677. .keyed {
  1678. color: rgba(170, 119, 204, 0.4); }
  1679. CSS
  1680. .keyed { color: rgba($color: #a7c, $alpha: 0.4) }
  1681. SCSS
  1682. end
  1683. def test_unknown_keyword_arg_raises_error
  1684. assert_raise_message(Sass::SyntaxError, "Mixin a doesn't have an argument named $c.") {render <<SCSS}
  1685. @mixin a($b: 1) { a: $b; }
  1686. div { @include a(1, $c: 3); }
  1687. SCSS
  1688. end
  1689. def test_newlines_removed_from_selectors_when_compressed
  1690. assert_equal <<CSS, render(<<SCSS, :style => :compressed)
  1691. z a,z b{display:block}
  1692. CSS
  1693. a
  1694. , b {
  1695. z & {
  1696. display: block;
  1697. }
  1698. }
  1699. SCSS
  1700. end
  1701. def test_if_error_line
  1702. assert_raise_line(2) {render(<<SCSS)}
  1703. @if true {foo: bar}
  1704. }
  1705. SCSS
  1706. end
  1707. def test_multiline_var
  1708. assert_equal <<CSS, render(<<SCSS)
  1709. foo {
  1710. a: 3;
  1711. b: false;
  1712. c: a b c; }
  1713. CSS
  1714. foo {
  1715. $var1: 1 +
  1716. 2;
  1717. $var2: true and
  1718. false;
  1719. $var3: a b
  1720. c;
  1721. a: $var1;
  1722. b: $var2;
  1723. c: $var3; }
  1724. SCSS
  1725. end
  1726. def test_mixin_content
  1727. assert_equal <<CSS, render(<<SASS)
  1728. .parent {
  1729. background-color: red;
  1730. border-color: red; }
  1731. .parent .child {
  1732. background-color: yellow;
  1733. color: blue;
  1734. border-color: yellow; }
  1735. CSS
  1736. $color: blue;
  1737. @mixin context($class, $color: red) {
  1738. .\#{$class} {
  1739. background-color: $color;
  1740. @content;
  1741. border-color: $color;
  1742. }
  1743. }
  1744. @include context(parent) {
  1745. @include context(child, $color: yellow) {
  1746. color: $color;
  1747. }
  1748. }
  1749. SASS
  1750. end
  1751. def test_empty_content
  1752. assert_equal <<CSS, render(<<SCSS)
  1753. a {
  1754. b: c; }
  1755. CSS
  1756. @mixin foo { @content }
  1757. a { b: c; @include foo {} }
  1758. SCSS
  1759. end
  1760. def test_options_passed_to_script
  1761. assert_equal <<CSS, render(<<SCSS, :style => :compressed)
  1762. foo{color:#000}
  1763. CSS
  1764. foo {color: darken(black, 10%)}
  1765. SCSS
  1766. end
  1767. # ref: https://github.com/nex3/sass/issues/104
  1768. def test_no_buffer_overflow
  1769. template = render <<SCSS
  1770. .aaa {
  1771. background-color: white;
  1772. }
  1773. .aaa .aaa .aaa {
  1774. background-color: black;
  1775. }
  1776. .bbb {
  1777. @extend .aaa;
  1778. }
  1779. .xxx {
  1780. @extend .bbb;
  1781. }
  1782. .yyy {
  1783. @extend .bbb;
  1784. }
  1785. .zzz {
  1786. @extend .bbb;
  1787. }
  1788. SCSS
  1789. Sass::SCSS::Parser.new(template, "test.scss").parse
  1790. end
  1791. def test_extend_in_media_in_rule
  1792. assert_equal(<<CSS, render(<<SCSS))
  1793. @media screen {
  1794. .foo {
  1795. a: b; } }
  1796. CSS
  1797. .foo {
  1798. @media screen {
  1799. @extend %bar;
  1800. }
  1801. }
  1802. @media screen {
  1803. %bar {
  1804. a: b;
  1805. }
  1806. }
  1807. SCSS
  1808. end
  1809. end