fix: Fix ColorCircles and Sizes initial render (no-changelog) (#9780)

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
Tomi Turtiainen 2024-06-17 15:51:00 +03:00 committed by GitHub
parent 12604fe1da
commit a484862576
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 145 additions and 20 deletions

View file

@ -59,6 +59,7 @@
"typescript": "*", "typescript": "*",
"vite": "^5.2.12", "vite": "^5.2.12",
"vitest": "^1.6.0", "vitest": "^1.6.0",
"vitest-mock-extended": "^1.3.1",
"vue-tsc": "^2.0.19" "vue-tsc": "^2.0.19"
}, },
"pnpm": { "pnpm": {

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { getHex, resolveHSLCalc } from './ColorCircles.utils'; import { getHex, resolveHSLCalc } from './ColorCircles.utils';
@ -10,23 +10,28 @@ const props = defineProps({
}, },
}); });
const hsl = reactive<{ [color: string]: string }>({}); const getColors = () => {
const observer = ref<MutationObserver | null>(null);
const setColors = () => {
for (const color of props.colors) {
const style = getComputedStyle(document.body); const style = getComputedStyle(document.body);
hsl[color] = style.getPropertyValue(color);
const hslColors: Record<string, string> = {};
for (const color of props.colors) {
const colorValue = style.getPropertyValue(color);
if (colorValue) {
hslColors[color] = colorValue;
} }
}
return hslColors;
}; };
onMounted(() => { const hsl = ref<{ [color: string]: string }>(getColors());
setColors(); const observer = ref<MutationObserver | null>(null);
onMounted(() => {
observer.value = new MutationObserver((mutationsList) => { observer.value = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) { for (const mutation of mutationsList) {
if (mutation.type === 'attributes') { if (mutation.type === 'attributes') {
setColors(); hsl.value = getColors();
} }
} }
}); });
@ -42,8 +47,8 @@ onUnmounted(() => {
}); });
// Expose functions for template usage // Expose functions for template usage
const getHexValue = (color: string) => getHex(hsl[color]); const getHexValue = (color: string) => getHex(hsl.value[color]);
const getHSLValue = (color: string) => resolveHSLCalc(hsl[color]); const getHSLValue = (color: string) => resolveHSLCalc(hsl.value[color]);
</script> </script>
<template> <template>

View file

@ -1,6 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { ref, onMounted, onUnmounted, reactive } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
type Size = {
rem: string;
px: number;
};
// Define props with their types // Define props with their types
const props = defineProps({ const props = defineProps({
@ -14,27 +19,29 @@ const props = defineProps({
}, },
}); });
const sizes = reactive<Record<string, { rem: string; px: number }>>({}); const getSizes = () => {
const observer = ref<MutationObserver | null>(null);
const setSizes = () => {
for (const variable of props.variables) {
const style = getComputedStyle(document.body); const style = getComputedStyle(document.body);
const sizeByVariableName: Record<string, Size> = {};
for (const variable of props.variables) {
const rem = style.getPropertyValue(variable); const rem = style.getPropertyValue(variable);
const px = parseFloat(rem.replace('rem', '')) * 16; // Assuming default font-size is 16px const px = parseFloat(rem.replace('rem', '')) * 16; // Assuming default font-size is 16px
sizes[variable] = { rem, px }; sizeByVariableName[variable] = { rem, px };
} }
return sizeByVariableName;
}; };
onMounted(() => { const sizes = ref<Record<string, Size>>(getSizes());
setSizes(); const observer = ref<MutationObserver | null>(null);
onMounted(() => {
// Observing attributes changes in body to recompute sizes // Observing attributes changes in body to recompute sizes
const mutationObserverCallback = (mutationsList: MutationRecord[]) => { const mutationObserverCallback = (mutationsList: MutationRecord[]) => {
for (const mutation of mutationsList) { for (const mutation of mutationsList) {
if (mutation.type === 'attributes') { if (mutation.type === 'attributes') {
setSizes(); sizes.value = getSizes();
} }
} }
}; };

View file

@ -0,0 +1,32 @@
import { render } from '@testing-library/vue';
import { mock, mockClear } from 'vitest-mock-extended';
import ColorCircles from '../ColorCircles.vue';
describe('ColorCircles', () => {
const mockCssDeclaration = mock<CSSStyleDeclaration>();
window.getComputedStyle = () => mockCssDeclaration;
beforeEach(() => {
mockClear(mockCssDeclaration);
});
it('should render an empty section with empty colors', () => {
const wrapper = render(ColorCircles, {
props: {
colors: [],
},
});
expect(wrapper.html()).toMatchSnapshot();
});
it('should render a section with two colors', () => {
mockCssDeclaration.getPropertyValue.mockReturnValue('#663399');
const wrapper = render(ColorCircles, {
props: {
colors: ['--color-primary-shade-1', '--color-primary'],
},
});
expect(wrapper.html()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,23 @@
import { render } from '@testing-library/vue';
import { mock, mockClear } from 'vitest-mock-extended';
import Sizes from '../Sizes.vue';
describe('Sizes', () => {
const mockCssDeclaration = mock<CSSStyleDeclaration>();
window.getComputedStyle = () => mockCssDeclaration;
beforeEach(() => {
mockClear(mockCssDeclaration);
});
it('should render a section with a variable', () => {
mockCssDeclaration.getPropertyValue.mockReturnValue('400');
const wrapper = render(Sizes, {
props: {
variables: ['--font-weight-regular'],
},
});
expect(wrapper.html()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,14 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ColorCircles > should render a section with two colors 1`] = `
"<div class="section">
<div class="container">
<div class="circle"></div><span>--color-primary-shade-1</span><span class="hsl">#663399</span><span class="color">#NaNNaNNaN</span>
</div>
<div class="container">
<div class="circle"></div><span>--color-primary</span><span class="hsl">#663399</span><span class="color">#NaNNaNNaN</span>
</div>
</div>"
`;
exports[`ColorCircles > should render an empty section with empty colors 1`] = `"<div class="section"></div>"`;

View file

@ -0,0 +1,16 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Sizes > should render a section with a variable 1`] = `
"<table class="table">
<tr>
<th class="row">Name</th>
<th class="row">rem</th>
<th class="row">px</th>
</tr>
<tr>
<td>--font-weight-regular</td>
<td>400</td>
<td>6400</td>
</tr>
</table>"
`;

View file

@ -110,6 +110,9 @@ importers:
vitest: vitest:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1) version: 1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1)
vitest-mock-extended:
specifier: ^1.3.1
version: 1.3.1(typescript@5.4.2)(vitest@1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1))
vue-tsc: vue-tsc:
specifier: ^2.0.19 specifier: ^2.0.19
version: 2.0.19(typescript@5.4.2) version: 2.0.19(typescript@5.4.2)
@ -12760,6 +12763,14 @@ packages:
peerDependencies: peerDependencies:
typescript: ^5.4.2 typescript: ^5.4.2
ts-essentials@9.4.2:
resolution: {integrity: sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==}
peerDependencies:
typescript: ^5.4.2
peerDependenciesMeta:
typescript:
optional: true
ts-ics@1.2.2: ts-ics@1.2.2:
resolution: {integrity: sha512-L7T5JQi99qQ2Uv7AoCHUZ8Mx1bJYo7qBZtBckuHueR90I3WVdW5NC/tOqTVgu18c3zj08du+xlgWlTIcE+Foxw==} resolution: {integrity: sha512-L7T5JQi99qQ2Uv7AoCHUZ8Mx1bJYo7qBZtBckuHueR90I3WVdW5NC/tOqTVgu18c3zj08du+xlgWlTIcE+Foxw==}
peerDependencies: peerDependencies:
@ -13245,6 +13256,12 @@ packages:
terser: terser:
optional: true optional: true
vitest-mock-extended@1.3.1:
resolution: {integrity: sha512-OpghYjh4BDuQ/Mzs3lFMQ1QRk9D8/2O9T47MLUA5eLn7K4RWIy+MfIivYOWEyxjTENjsBnzgMihDjyNalN/K0Q==}
peerDependencies:
typescript: ^5.4.2
vitest: '>=0.31.1'
vitest@1.6.0: vitest@1.6.0:
resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
@ -27877,6 +27894,10 @@ snapshots:
dependencies: dependencies:
typescript: 5.4.2 typescript: 5.4.2
ts-essentials@9.4.2(typescript@5.4.2):
optionalDependencies:
typescript: 5.4.2
ts-ics@1.2.2(date-fns@2.30.0)(lodash@4.17.21)(zod@3.23.8): ts-ics@1.2.2(date-fns@2.30.0)(lodash@4.17.21)(zod@3.23.8):
dependencies: dependencies:
date-fns: 2.30.0 date-fns: 2.30.0
@ -28372,6 +28393,12 @@ snapshots:
sass: 1.64.1 sass: 1.64.1
terser: 5.16.1 terser: 5.16.1
vitest-mock-extended@1.3.1(typescript@5.4.2)(vitest@1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1)):
dependencies:
ts-essentials: 9.4.2(typescript@5.4.2)
typescript: 5.4.2
vitest: 1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1)
vitest@1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1): vitest@1.6.0(@types/node@18.16.16)(jsdom@23.0.1)(sass@1.64.1)(terser@5.16.1):
dependencies: dependencies:
'@vitest/expect': 1.6.0 '@vitest/expect': 1.6.0