AccessibleThemeTestCase.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>
  4. *
  5. * @author Ferdinand Thiessen <opensource@fthiessen.de>
  6. *
  7. * @license AGPL-3.0-or-later
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace OCA\Theming\Tests\Themes;
  24. use OCA\Theming\ITheme;
  25. use OCA\Theming\Util;
  26. use Test\TestCase;
  27. class AccessibleThemeTestCase extends TestCase {
  28. protected ITheme $theme;
  29. protected Util $util;
  30. /**
  31. * Set to true to check for WCAG AAA level accessibility
  32. */
  33. protected bool $WCAGaaa = false;
  34. public function dataAccessibilityPairs() {
  35. $textContrast = $this->WCAGaaa ? 7.0 : 4.5;
  36. $elementContrast = 3.0;
  37. return [
  38. 'primary-element on background' => [
  39. [
  40. '--color-primary-element',
  41. '--color-primary-element-hover',
  42. ],
  43. [
  44. '--color-main-background',
  45. '--color-background-hover',
  46. '--color-background-dark',
  47. '--color-background-darker',
  48. '--color-main-background-blur',
  49. ],
  50. $elementContrast,
  51. ],
  52. 'status color elements on background' => [
  53. [
  54. '--color-error',
  55. '--color-error-hover',
  56. '--color-warning',
  57. '--color-warning-hover',
  58. '--color-info',
  59. '--color-info-hover',
  60. '--color-success',
  61. '--color-success-hover',
  62. '--color-favorite',
  63. ],
  64. [
  65. '--color-main-background',
  66. '--color-background-hover',
  67. '--color-background-dark',
  68. '--color-background-darker',
  69. '--color-main-background-blur',
  70. ],
  71. $elementContrast,
  72. ],
  73. 'border-colors' => [
  74. [
  75. '--color-border-maxcontrast',
  76. ],
  77. [
  78. '--color-main-background',
  79. '--color-background-hover',
  80. '--color-background-dark',
  81. '--color-main-background-blur',
  82. ],
  83. $elementContrast,
  84. ],
  85. // Those two colors are used for borders which will be `color-main-text` on focussed state, thus need 3:1 contrast to it
  86. 'success-error-border-colors' => [
  87. [
  88. '--color-error',
  89. '--color-success',
  90. ],
  91. [
  92. '--color-main-text',
  93. ],
  94. $elementContrast,
  95. ],
  96. 'primary-element-text' => [
  97. [
  98. '--color-primary-element-text',
  99. '--color-primary-element-text-dark',
  100. ],
  101. [
  102. '--color-primary-element',
  103. '--color-primary-element-hover',
  104. ],
  105. $textContrast,
  106. ],
  107. 'primary-element-light-text' => [
  108. ['--color-primary-element-light-text'],
  109. [
  110. '--color-primary-element-light',
  111. '--color-primary-element-light-hover',
  112. ],
  113. $textContrast,
  114. ],
  115. 'main-text' => [
  116. ['--color-main-text'],
  117. [
  118. '--color-main-background',
  119. '--color-background-hover',
  120. '--color-background-dark',
  121. '--color-background-darker',
  122. '--color-main-background-blur',
  123. ],
  124. $textContrast,
  125. ],
  126. 'max-contrast-text' => [
  127. ['--color-text-maxcontrast'],
  128. [
  129. '--color-main-background',
  130. '--color-background-hover',
  131. '--color-background-dark',
  132. ],
  133. $textContrast,
  134. ],
  135. 'max-contrast text-on blur' => [
  136. ['--color-text-maxcontrast-background-blur'],
  137. [
  138. '--color-main-background-blur',
  139. ],
  140. $textContrast,
  141. ],
  142. 'status-text' => [
  143. [
  144. '--color-error-text',
  145. '--color-warning-text',
  146. '--color-success-text',
  147. '--color-info-text',
  148. ],
  149. [
  150. '--color-main-background',
  151. '--color-background-hover',
  152. '--color-background-dark',
  153. '--color-main-background-blur',
  154. ],
  155. $textContrast,
  156. ],
  157. ];
  158. }
  159. /**
  160. * @dataProvider dataAccessibilityPairs
  161. */
  162. public function testAccessibilityOfVariables($mainColors, $backgroundColors, $minContrast) {
  163. if (!isset($this->theme)) {
  164. $this->markTestSkipped('You need to setup $this->theme in your setUp function');
  165. } elseif (!isset($this->util)) {
  166. $this->markTestSkipped('You need to setup $this->util in your setUp function');
  167. }
  168. $variables = $this->theme->getCSSVariables();
  169. // Blur effect does not work so we mockup the color - worst supported case is the default "clouds" background image (on dark themes the clouds with white color are bad on bright themes the primary color as sky is bad)
  170. $variables['--color-main-background-blur'] = $this->util->mix($variables['--color-main-background'], $this->util->isBrightColor($variables['--color-main-background']) ? '#000000' : '#ffffff', 75);
  171. foreach ($backgroundColors as $background) {
  172. $this->assertStringStartsWith('#', $variables[$background], 'Is not a plain color variable - consider to remove or fix this test');
  173. foreach ($mainColors as $main) {
  174. $this->assertStringStartsWith('#', $variables[$main], 'Is not a plain color variable - consider to remove or fix this test');
  175. $realContrast = $this->util->colorContrast($variables[$main], $variables[$background]);
  176. $this->assertGreaterThanOrEqual($minContrast, $realContrast, "Contrast is not high enough for $main (" . $variables[$main] . ") on $background (" . $variables[$background] . ')');
  177. }
  178. }
  179. }
  180. }