api-native-theme-spec.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { expect } from 'chai';
  2. import { nativeTheme, systemPreferences, BrowserWindow, ipcMain } from 'electron/main';
  3. import { once } from 'node:events';
  4. import * as path from 'node:path';
  5. import { setTimeout } from 'node:timers/promises';
  6. import { expectDeprecationMessages } from './lib/deprecate-helpers';
  7. import { ifdescribe } from './lib/spec-helpers';
  8. import { closeAllWindows } from './lib/window-helpers';
  9. describe('nativeTheme module', () => {
  10. describe('nativeTheme.shouldUseDarkColors', () => {
  11. it('returns a boolean', () => {
  12. expect(nativeTheme.shouldUseDarkColors).to.be.a('boolean');
  13. });
  14. });
  15. describe('nativeTheme.themeSource', () => {
  16. afterEach(async () => {
  17. nativeTheme.themeSource = 'system';
  18. // Wait for any pending events to emit
  19. await setTimeout(20);
  20. closeAllWindows();
  21. });
  22. it('is system by default', () => {
  23. expect(nativeTheme.themeSource).to.equal('system');
  24. });
  25. it('should override the value of shouldUseDarkColors', () => {
  26. nativeTheme.themeSource = 'dark';
  27. expect(nativeTheme.shouldUseDarkColors).to.equal(true);
  28. nativeTheme.themeSource = 'light';
  29. expect(nativeTheme.shouldUseDarkColors).to.equal(false);
  30. });
  31. it('should emit the "updated" event when it is set and the resulting "shouldUseDarkColors" value changes', async () => {
  32. nativeTheme.themeSource = 'light';
  33. let updatedEmitted = once(nativeTheme, 'updated');
  34. nativeTheme.themeSource = 'dark';
  35. await updatedEmitted;
  36. updatedEmitted = once(nativeTheme, 'updated');
  37. nativeTheme.themeSource = 'light';
  38. await updatedEmitted;
  39. });
  40. it('should not emit the "updated" event when it is set and the resulting "shouldUseDarkColors" value is the same', async () => {
  41. nativeTheme.themeSource = 'dark';
  42. // Wait a few ticks to allow an async events to flush
  43. await setTimeout(20);
  44. let called = false;
  45. nativeTheme.once('updated', () => {
  46. called = true;
  47. });
  48. nativeTheme.themeSource = 'dark';
  49. // Wait a few ticks to allow an async events to flush
  50. await setTimeout(20);
  51. expect(called).to.equal(false);
  52. });
  53. ifdescribe(process.platform === 'darwin')('on macOS', () => {
  54. it('should update appLevelAppearance when set', async () => {
  55. await expectDeprecationMessages(
  56. () => {
  57. nativeTheme.themeSource = 'dark';
  58. expect(systemPreferences.appLevelAppearance).to.equal('dark');
  59. nativeTheme.themeSource = 'light';
  60. expect(systemPreferences.appLevelAppearance).to.equal('light');
  61. },
  62. "(electron) 'appLevelAppearance' is deprecated and will be removed."
  63. );
  64. });
  65. });
  66. const getPrefersColorSchemeIsDark = async (w: Electron.BrowserWindow) => {
  67. const isDark: boolean = await w.webContents.executeJavaScript(
  68. 'matchMedia("(prefers-color-scheme: dark)").matches'
  69. );
  70. return isDark;
  71. };
  72. it('should override the result of prefers-color-scheme CSS media query', async () => {
  73. const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: false, nodeIntegration: true } });
  74. await w.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
  75. await w.webContents.executeJavaScript(`
  76. window.matchMedia('(prefers-color-scheme: dark)')
  77. .addEventListener('change', () => require('electron').ipcRenderer.send('theme-change'))
  78. `);
  79. const originalSystemIsDark = await getPrefersColorSchemeIsDark(w);
  80. let changePromise = once(ipcMain, 'theme-change');
  81. nativeTheme.themeSource = 'dark';
  82. if (!originalSystemIsDark) await changePromise;
  83. expect(await getPrefersColorSchemeIsDark(w)).to.equal(true);
  84. changePromise = once(ipcMain, 'theme-change');
  85. nativeTheme.themeSource = 'light';
  86. await changePromise;
  87. expect(await getPrefersColorSchemeIsDark(w)).to.equal(false);
  88. changePromise = once(ipcMain, 'theme-change');
  89. nativeTheme.themeSource = 'system';
  90. if (originalSystemIsDark) await changePromise;
  91. expect(await getPrefersColorSchemeIsDark(w)).to.equal(originalSystemIsDark);
  92. w.close();
  93. });
  94. });
  95. describe('nativeTheme.shouldUseInvertedColorScheme', () => {
  96. it('returns a boolean', () => {
  97. expect(nativeTheme.shouldUseInvertedColorScheme).to.be.a('boolean');
  98. });
  99. });
  100. describe('nativeTheme.shouldUseHighContrastColors', () => {
  101. it('returns a boolean', () => {
  102. expect(nativeTheme.shouldUseHighContrastColors).to.be.a('boolean');
  103. });
  104. });
  105. describe('nativeTheme.inForcedColorsMode', () => {
  106. it('returns a boolean', () => {
  107. expect(nativeTheme.inForcedColorsMode).to.be.a('boolean');
  108. });
  109. });
  110. });