Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistent avatar colors #13

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
feca248
feat: compareColors function
Miki-Session Nov 12, 2024
7958932
feat: check avatar color test spec
Miki-Session Nov 12, 2024
d48f220
remove logging
Miki-Session Nov 12, 2024
95da703
add separate linked device spec
Miki-Session Nov 12, 2024
573260f
compareColors doesn't need to be async
Miki-Session Nov 13, 2024
915a306
Merge branch 'onboarding-modals' into consistent-account-colors
Miki-Session Nov 13, 2024
43edb39
fix: explicitly type isSameColor
Miki-Session Nov 13, 2024
11fc2ad
chore: eslint errors
Miki-Session Nov 13, 2024
0705585
fix: looks-same is a devdependency not a dependency
Miki-Session Nov 13, 2024
954949e
Merge remote-tracking branch 'stf/main' into consistent-account-colors
Miki-Session Nov 18, 2024
adc9563
Merge remote-tracking branch 'stf/main' into consistent-account-colors
Miki-Session Nov 18, 2024
76038d7
fix: ConversationAvatar locator class iOS case
Miki-Session Nov 18, 2024
3ef1710
chore: yarn lint
Miki-Session Nov 18, 2024
273f6ed
chore: bump typescript-eslint to 8.15.0
Miki-Session Dec 10, 2024
e2f5149
fix: address test spec feedback
Miki-Session Jan 7, 2025
4fecfda
fix: begin simplifying the compareColors function
Miki-Session Jan 7, 2025
5337172
Merge remote-tracking branch 'stf/main' into consistent-account-colors
Miki-Session Jan 7, 2025
0c6b567
fix: remove platform from newUser and linkedDevice
Miki-Session Jan 7, 2025
359b485
fix: move hexToRgbObject to utilities.ts, rename compareColors functi…
Miki-Session Jan 8, 2025
2fc2832
fix: remove explicit typing for isSameColor
Miki-Session Jan 8, 2025
d5a50a9
fix: wrap device1 and device2.navigateBack in await Promise.all
Miki-Session Jan 13, 2025
1eaee50
chore: comment about conversation avatars per platform
Miki-Session Jan 13, 2025
1852c5b
chore: explain which elements are being compared
Miki-Session Jan 13, 2025
3d34a4c
chore: yarn lint
Miki-Session Jan 13, 2025
312cc67
feat: add getElementPixelColor function
Miki-Session Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions run/test/specs/check_avatar_color.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { USERNAME } from '../../types/testing';
import { newUser } from './utils/create_account';
import { newContact } from './utils/create_contact';
import { SupportedPlatformsType, closeApp, openAppTwoDevices } from './utils/open_app';
import { compareColors, parseDataImage } from './utils/check_colour';
import { isSameColor, parseDataImage } from './utils/check_colour';
import { UserSettings } from './locators/settings';
import { ConversationItem } from './locators/home';
import { ConversationAvatar, ConversationSettings } from './locators/conversation';
Expand All @@ -13,8 +13,8 @@ bothPlatformsIt('Avatar color', 'medium', avatarColor);
async function avatarColor(platform: SupportedPlatformsType) {
const { device1, device2 } = await openAppTwoDevices(platform);
const [userA, userB] = await Promise.all([
newUser(device1, USERNAME.ALICE, platform),
newUser(device2, USERNAME.BOB, platform),
newUser(device1, USERNAME.ALICE),
newUser(device2, USERNAME.BOB),
]);
await newContact(platform, device1, userA, device2, userB);
await device1.navigateBack();
Expand All @@ -33,16 +33,12 @@ async function avatarColor(platform: SupportedPlatformsType) {
}
const device2Base64 = await device2.getElementScreenshot(device2Avatar.ELEMENT);
const device2PixelColor = await parseDataImage(device2Base64);
// Color comparison of devices 1 and 2
const colorCompare = compareColors(device1PixelColor, device2PixelColor);
if (!colorCompare) {
// Color matching devices 1 and 2
const colorMatch = isSameColor(device1PixelColor, device2PixelColor);
if (!colorMatch) {
throw new Error(
`The avatar color of ${userA.userName} does not match across devices. The colors are ${device1PixelColor} and ${device2PixelColor}`
);
} else {
console.log(
`The default avatar color of ${userA.userName} is within tolerance across devices.`
);
}
await closeApp(device1, device2);
}
14 changes: 5 additions & 9 deletions run/test/specs/linked_device_avatar_color.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { bothPlatformsIt } from '../../types/sessionIt';
import { USERNAME } from '../../types/testing';
import { linkedDevice } from './utils/link_device';
import { SupportedPlatformsType, closeApp, openAppTwoDevices } from './utils/open_app';
import { compareColors, parseDataImage } from './utils/check_colour';
import { isSameColor, parseDataImage } from './utils/check_colour';
import { UserSettings } from './locators/settings';

bothPlatformsIt('Avatar color linked device', 'medium', avatarColorLinkedDevice);

async function avatarColorLinkedDevice(platform: SupportedPlatformsType) {
const { device1, device2 } = await openAppTwoDevices(platform);
const userA = await linkedDevice(device1, device2, USERNAME.ALICE, platform);
const userA = await linkedDevice(device1, device2, USERNAME.ALICE);
// Get Alice's avatar color on device 1 and turn it into a hex value
const device1Avatar = await device1.waitForTextElementToBePresent(new UserSettings(device1));
const device1Base64 = await device1.getElementScreenshot(device1Avatar.ELEMENT);
Expand All @@ -18,16 +18,12 @@ async function avatarColorLinkedDevice(platform: SupportedPlatformsType) {
const device2Avatar = await device2.waitForTextElementToBePresent(new UserSettings(device2));
const device2Base64 = await device2.getElementScreenshot(device2Avatar.ELEMENT);
const device2PixelColor = await parseDataImage(device2Base64);
// Color comparison of devices 1 and 2
const colorCompare = compareColors(device1PixelColor, device2PixelColor);
if (!colorCompare) {
// Color matching devices 1 and 2
const colorMatch = isSameColor(device1PixelColor, device2PixelColor);
if (!colorMatch) {
throw new Error(
`The avatar color of ${userA.userName} does not match across devices. The colors are ${device1PixelColor} and ${device2PixelColor}`
);
} else {
console.log(
`The default avatar color of ${userA.userName} is within tolerance across devices.`
);
}
await closeApp(device1, device2);
}
26 changes: 6 additions & 20 deletions run/test/specs/utils/check_colour.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import PNG from 'png-js';
import { colors } from 'looks-same';
import { hexToRgbObject } from './utilities';

export async function parseDataImage(base64: string) {
const buffer = Buffer.from(base64, 'base64');
Expand All @@ -25,27 +26,12 @@ export async function parseDataImage(base64: string) {
return pixelColor;
}

// Function to compare two colors within a specified CIEDE2000 tolerance
export function compareColors(
hex1: string,
hex2: string,
tolerance: number = 2.3 // looks-same default value which is "enough for most cases"
): boolean {
// looks-same expects colors as RGB objects but parseDataImage outputs hex
function hexToRgbObject(hex: string): { R: number; G: number; B: number } {
const bigint = parseInt(hex.replace('#', ''), 16);
return {
R: (bigint >> 16) & 255,
G: (bigint >> 8) & 255,
B: bigint & 255,
};
}
// RGB-HEX conversion
// Determines if two colors look "the same" for humans even if they are not an exact match
export function isSameColor(hex1: string, hex2: string) {
// Convert the hex strings to RGB objects
const rgb1 = hexToRgbObject(hex1);
const rgb2 = hexToRgbObject(hex2);

// Compare whether colors are within tolerance
const isSameColor: boolean = colors(rgb1, rgb2, { tolerance });

// Perform the color comparison using the looks-same library
const isSameColor: boolean = colors(rgb1, rgb2);
Miki-Session marked this conversation as resolved.
Show resolved Hide resolved
return isSameColor;
}
13 changes: 13 additions & 0 deletions run/test/specs/utils/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,16 @@ export const isDeviceAndroid = (device: unknown) => !isDeviceIOS(device);
export const isCI = () => {
return process.env.NODE_CONFIG_ENV === 'ci';
};

// Converts a hexadecimal color string to an RGB object
export function hexToRgbObject(hex: string): { R: number; G: number; B: number } {
// Parse the hexadecimal string into a decimal number
// Removes the # prefix if present and converts the remaining string to base-10
const decimalValue = parseInt(hex.replace('#', ''), 16);
// Extract the red, green, and blue components using bitwise operations
return {
R: (decimalValue >> 16) & 255,
G: (decimalValue >> 8) & 255,
B: decimalValue & 255,
};
}
Loading