AccessibleThemeTestCase.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. ],
  63. [
  64. '--color-main-background',
  65. '--color-background-hover',
  66. '--color-background-dark',
  67. '--color-background-darker',
  68. '--color-main-background-blur',
  69. ],
  70. $elementContrast,
  71. ],
  72. 'border-colors' => [
  73. [
  74. '--color-border-maxcontrast',
  75. ],
  76. [
  77. '--color-main-background',
  78. '--color-background-hover',
  79. '--color-background-dark',
  80. '--color-main-background-blur',
  81. ],
  82. $elementContrast,
  83. ],
  84. // Those two colors are used for borders which will be `color-main-text` on focussed state, thus need 3:1 contrast to it
  85. 'success-error-border-colors' => [
  86. [
  87. '--color-error',
  88. '--color-success',
  89. ],
  90. [
  91. '--color-main-text',
  92. ],
  93. $elementContrast,
  94. ],
  95. 'primary-element-text' => [
  96. [
  97. '--color-primary-element-text',
  98. '--color-primary-element-text-dark',
  99. ],
  100. [
  101. '--color-primary-element',
  102. '--color-primary-element-hover',
  103. ],
  104. $textContrast,
  105. ],
  106. 'primary-element-light-text' => [
  107. ['--color-primary-element-light-text'],
  108. [
  109. '--color-primary-element-light',
  110. '--color-primary-element-light-hover',
  111. ],
  112. $textContrast,
  113. ],
  114. 'main-text' => [
  115. ['--color-main-text'],
  116. [
  117. '--color-main-background',
  118. '--color-background-hover',
  119. '--color-background-dark',
  120. '--color-background-darker',
  121. '--color-main-background-blur',
  122. ],
  123. $textContrast,
  124. ],
  125. 'max-contrast-text' => [
  126. ['--color-text-maxcontrast'],
  127. [
  128. '--color-main-background',
  129. '--color-background-hover',
  130. '--color-background-dark',
  131. ],
  132. $textContrast,
  133. ],
  134. 'max-contrast text-on blur' => [
  135. ['--color-text-maxcontrast-background-blur'],
  136. [
  137. '--color-main-background-blur',
  138. ],
  139. $textContrast,
  140. ],
  141. 'status-text' => [
  142. [
  143. '--color-error-text',
  144. '--color-warning-text',
  145. '--color-success-text',
  146. '--color-info-text',
  147. ],
  148. [
  149. '--color-main-background',
  150. '--color-background-hover',
  151. '--color-background-dark',
  152. '--color-main-background-blur',
  153. ],
  154. $textContrast,
  155. ],
  156. ];
  157. }
  158. /**
  159. * @dataProvider dataAccessibilityPairs
  160. */
  161. public function testAccessibilityOfVariables($mainColors, $backgroundColors, $minContrast) {
  162. if (!isset($this->theme)) {
  163. $this->markTestSkipped('You need to setup $this->theme in your setUp function');
  164. } elseif (!isset($this->util)) {
  165. $this->markTestSkipped('You need to setup $this->util in your setUp function');
  166. }
  167. $variables = $this->theme->getCSSVariables();
  168. // 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)
  169. $variables['--color-main-background-blur'] = $this->util->mix($variables['--color-main-background'], $this->util->isBrightColor($variables['--color-main-background']) ? '#000000' : '#ffffff', 75);
  170. foreach ($backgroundColors as $background) {
  171. $this->assertStringStartsWith('#', $variables[$background], 'Is not a plain color variable - consider to remove or fix this test');
  172. foreach ($mainColors as $main) {
  173. $this->assertStringStartsWith('#', $variables[$main], 'Is not a plain color variable - consider to remove or fix this test');
  174. $realContrast = $this->util->colorContrast($variables[$main], $variables[$background]);
  175. $this->assertGreaterThanOrEqual($minContrast, $realContrast, "Contrast is not high enough for $main (" . $variables[$main] . ") on $background (" . $variables[$background] . ')');
  176. }
  177. }
  178. }
  179. }