AccessibleThemeTestCase.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OCA\Theming\Tests\Themes;
  7. use OCA\Theming\ITheme;
  8. use OCA\Theming\Util;
  9. use Test\TestCase;
  10. class AccessibleThemeTestCase extends TestCase {
  11. protected ITheme $theme;
  12. protected Util $util;
  13. /**
  14. * Set to true to check for WCAG AAA level accessibility
  15. */
  16. protected bool $WCAGaaa = false;
  17. public function dataAccessibilityPairs() {
  18. $textContrast = $this->WCAGaaa ? 7.0 : 4.5;
  19. $elementContrast = 3.0;
  20. return [
  21. 'primary-element on background' => [
  22. [
  23. '--color-primary-element',
  24. '--color-primary-element-hover',
  25. ],
  26. [
  27. '--color-main-background',
  28. '--color-background-hover',
  29. '--color-background-dark',
  30. '--color-background-darker',
  31. '--color-main-background-blur',
  32. ],
  33. $elementContrast,
  34. ],
  35. 'status color elements on background' => [
  36. [
  37. '--color-error',
  38. '--color-error-hover',
  39. '--color-warning',
  40. '--color-warning-hover',
  41. '--color-info',
  42. '--color-info-hover',
  43. '--color-success',
  44. '--color-success-hover',
  45. '--color-favorite',
  46. ],
  47. [
  48. '--color-main-background',
  49. '--color-background-hover',
  50. '--color-background-dark',
  51. '--color-background-darker',
  52. '--color-main-background-blur',
  53. ],
  54. $elementContrast,
  55. ],
  56. 'border-colors' => [
  57. [
  58. '--color-border-maxcontrast',
  59. ],
  60. [
  61. '--color-main-background',
  62. '--color-background-hover',
  63. '--color-background-dark',
  64. '--color-main-background-blur',
  65. ],
  66. $elementContrast,
  67. ],
  68. // Those two colors are used for borders which will be `color-main-text` on focussed state, thus need 3:1 contrast to it
  69. 'success-error-border-colors' => [
  70. [
  71. '--color-error',
  72. '--color-success',
  73. ],
  74. [
  75. '--color-main-text',
  76. ],
  77. $elementContrast,
  78. ],
  79. 'primary-element-text' => [
  80. [
  81. '--color-primary-element-text',
  82. '--color-primary-element-text-dark',
  83. ],
  84. [
  85. '--color-primary-element',
  86. '--color-primary-element-hover',
  87. ],
  88. $textContrast,
  89. ],
  90. 'primary-element-light-text' => [
  91. ['--color-primary-element-light-text'],
  92. [
  93. '--color-primary-element-light',
  94. '--color-primary-element-light-hover',
  95. ],
  96. $textContrast,
  97. ],
  98. 'main-text' => [
  99. ['--color-main-text'],
  100. [
  101. '--color-main-background',
  102. '--color-background-hover',
  103. '--color-background-dark',
  104. '--color-background-darker',
  105. '--color-main-background-blur',
  106. ],
  107. $textContrast,
  108. ],
  109. 'max-contrast-text' => [
  110. ['--color-text-maxcontrast'],
  111. [
  112. '--color-main-background',
  113. '--color-background-hover',
  114. '--color-background-dark',
  115. ],
  116. $textContrast,
  117. ],
  118. 'max-contrast text-on blur' => [
  119. ['--color-text-maxcontrast-background-blur'],
  120. [
  121. '--color-main-background-blur',
  122. ],
  123. $textContrast,
  124. ],
  125. 'status-text' => [
  126. [
  127. '--color-error-text',
  128. '--color-warning-text',
  129. '--color-success-text',
  130. '--color-info-text',
  131. ],
  132. [
  133. '--color-main-background',
  134. '--color-background-hover',
  135. '--color-background-dark',
  136. '--color-main-background-blur',
  137. ],
  138. $textContrast,
  139. ],
  140. ];
  141. }
  142. /**
  143. * @dataProvider dataAccessibilityPairs
  144. */
  145. public function testAccessibilityOfVariables($mainColors, $backgroundColors, $minContrast): void {
  146. if (!isset($this->theme)) {
  147. $this->markTestSkipped('You need to setup $this->theme in your setUp function');
  148. } elseif (!isset($this->util)) {
  149. $this->markTestSkipped('You need to setup $this->util in your setUp function');
  150. }
  151. $variables = $this->theme->getCSSVariables();
  152. // 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)
  153. $variables['--color-main-background-blur'] = $this->util->mix($variables['--color-main-background'], $this->util->isBrightColor($variables['--color-main-background']) ? '#000000' : '#ffffff', 75);
  154. foreach ($backgroundColors as $background) {
  155. $this->assertStringStartsWith('#', $variables[$background], 'Is not a plain color variable - consider to remove or fix this test');
  156. foreach ($mainColors as $main) {
  157. $this->assertStringStartsWith('#', $variables[$main], 'Is not a plain color variable - consider to remove or fix this test');
  158. $realContrast = $this->util->colorContrast($variables[$main], $variables[$background]);
  159. $this->assertGreaterThanOrEqual($minContrast, $realContrast, "Contrast is not high enough for $main (" . $variables[$main] . ") on $background (" . $variables[$background] . ')');
  160. }
  161. }
  162. }
  163. }