mirror of
https://github.com/apache/superset.git
synced 2026-07-28 09:32:28 +00:00
Compare commits
4 Commits
dependabot
...
fix-sqllab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206761adfe | ||
|
|
48aba96326 | ||
|
|
156aaf3539 | ||
|
|
5c37d178f8 |
@@ -18,7 +18,11 @@
|
||||
*/
|
||||
import { createRef } from 'react';
|
||||
import { render, screen, waitFor } from '@superset-ui/core/spec';
|
||||
import { supersetTheme } from '@apache-superset/core/theme';
|
||||
import {
|
||||
supersetTheme,
|
||||
ThemeProvider,
|
||||
type SupersetTheme,
|
||||
} from '@apache-superset/core/theme';
|
||||
import type AceEditor from 'react-ace';
|
||||
import {
|
||||
AsyncAceEditor,
|
||||
@@ -30,6 +34,7 @@ import {
|
||||
JsonEditor,
|
||||
ConfigEditor,
|
||||
aceCompletionHighlightStyles,
|
||||
aceSelectedWordStyles,
|
||||
} from '.';
|
||||
|
||||
import type { AceModule, AsyncAceEditorOptions } from './types';
|
||||
@@ -55,6 +60,81 @@ test('themes the autocomplete completion highlight from the theme', () => {
|
||||
expect(styles).toContain(supersetTheme.colorPrimaryText);
|
||||
});
|
||||
|
||||
test('themes the selected-word occurrence markers from the theme', () => {
|
||||
// The light `github` theme hardcodes a near-white box for the markers Ace
|
||||
// paints on every other occurrence of the selected token, which makes the
|
||||
// recolored token glyphs unreadable in dark mode. The shared editor overrides
|
||||
// the marker to reuse the dark-aware selection color so it stays legible.
|
||||
const { styles } = aceSelectedWordStyles(supersetTheme);
|
||||
|
||||
expect(styles).toContain('.ace_selected-word');
|
||||
// The default theme leaves `colorEditorSelection` unset, so the marker uses
|
||||
// the documented `colorPrimaryBgHover` fallback.
|
||||
expect(styles).toContain(supersetTheme.colorPrimaryBgHover);
|
||||
// The override also restyles the marker border from the theme...
|
||||
expect(styles).toContain(supersetTheme.colorBorder);
|
||||
// ...and carries `!important`, which is what lets it win over Ace's bundled
|
||||
// non-important `.ace-github .ace_marker-layer .ace_selected-word` near-white
|
||||
// rule regardless of stylesheet order (the effective-cascade guarantee that
|
||||
// jsdom cannot verify by computed style).
|
||||
expect(styles).toContain('!important');
|
||||
});
|
||||
|
||||
// Collect every CSS rule the render injected: emotion's Global styles land in
|
||||
// <style> tags (non-speedy in test) while Ace's bundled theme uses the CSSOM,
|
||||
// so read both to reliably observe what actually reached the document.
|
||||
function getInjectedCss(): string {
|
||||
const fromTags = Array.from(document.querySelectorAll('style'))
|
||||
.map(tag => tag.textContent ?? '')
|
||||
.join('\n');
|
||||
const fromSheets = Array.from(document.styleSheets)
|
||||
.map(sheet => {
|
||||
try {
|
||||
return Array.from(sheet.cssRules)
|
||||
.map(rule => rule.cssText)
|
||||
.join('\n');
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
return `${fromTags}\n${fromSheets}`;
|
||||
}
|
||||
|
||||
test('wires the dark-aware selected-word marker into the editor Global styles', async () => {
|
||||
// Guards the actual regression: Ace's bundled `github` theme already injects
|
||||
// a near-white `.ace-github ... .ace_selected-word` rule, so the fix is only
|
||||
// effective if the editor's own Global block also emits a `.ace_selected-word`
|
||||
// override driven by the theme. Render with a distinctive `colorEditorSelection`
|
||||
// and assert that value reaches the injected selected-word rule — this fails if
|
||||
// the `${aceSelectedWordStyles(token)}` interpolation is dropped from <Global>.
|
||||
const markerColor = '#010203';
|
||||
const darkTheme: SupersetTheme = {
|
||||
...supersetTheme,
|
||||
colorEditorSelection: markerColor,
|
||||
};
|
||||
|
||||
// The shared `render` helper injects its own default `SupersetThemeProvider`,
|
||||
// so nest the dark theme around the editor itself: the innermost emotion
|
||||
// `ThemeProvider` is what the editor's `useTheme()` resolves.
|
||||
const { container } = render(
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<SQLEditor />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector('[id="ace-editor"]')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const css = getInjectedCss();
|
||||
// The dark-aware color is tied specifically to the selected-word marker
|
||||
// (not just the plain `.ace_selection`), so the occurrence markers inherit it.
|
||||
expect(css).toMatch(
|
||||
new RegExp(`\\.ace_selected-word[^}]*${markerColor}`, 'i'),
|
||||
);
|
||||
});
|
||||
|
||||
test('SQLEditor uses fontFamilyCode from theme', async () => {
|
||||
const ref = createRef<AceEditor>();
|
||||
const { container } = render(<SQLEditor ref={ref as React.Ref<never>} />);
|
||||
|
||||
@@ -113,6 +113,14 @@ export type AsyncAceEditorOptions = {
|
||||
> | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dark-aware color for text selection in the editor. Shared so the plain
|
||||
* selection and the "selected word" occurrence markers always match, falling
|
||||
* back to `colorPrimaryBgHover` on themes that don't define the token.
|
||||
*/
|
||||
export const editorSelectionColor = (token: SupersetTheme) =>
|
||||
token.colorEditorSelection ?? token.colorPrimaryBgHover;
|
||||
|
||||
/**
|
||||
* Theme-aware styling for the matched-prefix highlight in the autocomplete
|
||||
* popup. Ace ships a hardcoded `color: #000` that is invisible on the dark
|
||||
@@ -126,6 +134,20 @@ export const aceCompletionHighlightStyles = (token: SupersetTheme) => css`
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Theme-aware styling for the "selected word" markers Ace paints on every other
|
||||
* occurrence of the currently selected token. The light `github` theme hardcodes
|
||||
* a near-white box (`rgb(250,250,255)`); in dark mode the recolored token glyphs
|
||||
* sit on it unreadably. Reuse the same dark-aware selection color as
|
||||
* `.ace_selection` so the markers stay legible in every theme.
|
||||
*/
|
||||
export const aceSelectedWordStyles = (token: SupersetTheme) => css`
|
||||
.ace_editor .ace_marker-layer .ace_selected-word {
|
||||
background-color: ${editorSelectionColor(token)} !important;
|
||||
border: 1px solid ${token.colorBorder} !important;
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Get an async AceEditor with automatical loading of specified ace modules.
|
||||
*/
|
||||
@@ -389,11 +411,11 @@ export function AsyncAceEditor(
|
||||
}
|
||||
/* Adjust selection color */
|
||||
.ace_editor .ace_selection {
|
||||
background-color: ${
|
||||
token.colorEditorSelection ?? token.colorPrimaryBgHover
|
||||
} !important;
|
||||
background-color: ${editorSelectionColor(token)} !important;
|
||||
}
|
||||
|
||||
${aceSelectedWordStyles(token)}
|
||||
|
||||
/* Improve active line highlighting */
|
||||
.ace_editor .ace_active-line {
|
||||
background-color: ${token.colorPrimaryBg} !important;
|
||||
|
||||
Reference in New Issue
Block a user