Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
68 changes: 68 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,71 @@
# v5.1.2 (Mon Apr 13 2026)

#### 🐛 Bug Fix

- Sidebar: add clear() to test provider to clear visual test statuses [#421](https://github.com/chromaui/addon-visual-tests/pull/421) ([@valentinpalkovic](https://github.com/valentinpalkovic))

#### Authors: 1

- Valentin Palkovic ([@valentinpalkovic](https://github.com/valentinpalkovic))

---

# v5.1.1 (Thu Mar 26 2026)

#### 🐛 Bug Fix

- Fix preview errors [#416](https://github.com/chromaui/addon-visual-tests/pull/416) ([@JReinhold](https://github.com/JReinhold))

#### Authors: 2

- Gert Hengeveld ([@ghengeveld](https://github.com/ghengeveld))
- Jeppe Reinhold ([@JReinhold](https://github.com/JReinhold))

---

# v5.1.0 (Wed Mar 25 2026)

#### 🚀 Enhancement

- Add tool to highlight ignored elements [#411](https://github.com/chromaui/addon-visual-tests/pull/411) ([@ghengeveld](https://github.com/ghengeveld))

#### Authors: 1

- Gert Hengeveld ([@ghengeveld](https://github.com/ghengeveld))

---

# v5.0.2 (Thu Mar 19 2026)

#### 🐛 Bug Fix

- chore: Allow 10.4 prerelease peers [#412](https://github.com/chromaui/addon-visual-tests/pull/412) ([@Sidnioulz](https://github.com/Sidnioulz))

#### Authors: 2

- Steve Dodier-Lazaro ([@Sidnioulz](https://github.com/Sidnioulz))
- Yann Braga ([@yannbf](https://github.com/yannbf))

---

# v5.0.1 (Mon Feb 09 2026)

#### 🐛 Bug Fix

- feat: Add CSF Next compatibility for definePreview addons pattern [#404](https://github.com/chromaui/addon-visual-tests/pull/404) ([@jthrilly](https://github.com/jthrilly) [@valentinpalkovic](https://github.com/valentinpalkovic))
- upgrade storybook to latest [#406](https://github.com/chromaui/addon-visual-tests/pull/406) ([@ndelangen](https://github.com/ndelangen))
- Main > Next sync [#407](https://github.com/chromaui/addon-visual-tests/pull/407) ([@ndelangen](https://github.com/ndelangen) [@chromatic-support](https://github.com/chromatic-support) [@ghengeveld](https://github.com/ghengeveld))

#### Authors: 5

- [@chromatic-support](https://github.com/chromatic-support)
- Gert Hengeveld ([@ghengeveld](https://github.com/ghengeveld))
- Joshua Melville ([@jthrilly](https://github.com/jthrilly))
- Norbert de Langen ([@ndelangen](https://github.com/ndelangen))
- Valentin Palkovic ([@valentinpalkovic](https://github.com/valentinpalkovic))

---

# v5.0.0 (Tue Jan 13 2026)

#### 💥 Breaking Change
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chromatic-com/storybook",
"version": "5.0.0",
"version": "5.1.2",
"description": "Catch unexpected visual changes & UI bugs in your stories",
"keywords": [
"storybook-addons",
Expand Down
5 changes: 4 additions & 1 deletion src/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ addons.register(ADDON_ID, (api) => {

addons.add(TEST_PROVIDER_ID, {
type: Addon_TypesEnum.experimental_TEST_PROVIDER,
clear: () => {
statusStore.unset();
},
render: () => <TestProviderRender />,
} satisfies Omit<Addon_TestProviderType, 'id'>);
} as Omit<Addon_TestProviderType, 'id'>);
});
67 changes: 67 additions & 0 deletions src/utils/requestAccessToken.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { initiateSignin } from './requestAccessToken';

describe('requestAccessToken', () => {
const fetchMock = vi.fn();

beforeEach(() => {
vi.stubGlobal('fetch', fetchMock);
vi.stubGlobal('window', {
btoa: (value: string) => Buffer.from(value, 'binary').toString('base64'),
});
vi.spyOn(Math, 'random').mockReturnValue(0.123456789);
});

afterEach(() => {
fetchMock.mockReset();
vi.restoreAllMocks();
vi.unstubAllGlobals();
});

it('uses the SSO subdomain for the authorize request and verification URL', async () => {
fetchMock.mockResolvedValue({
json: async () => ({
device_code: 'device-code',
user_code: '123 123',
verification_uri_complete:
'https://www.chromatic.com/connect/chromaui:addon-visual-tests?code=123123',
expires_in: 300,
interval: 5,
}),
});

const result = await initiateSignin('rocket');

expect(fetchMock).toHaveBeenCalledWith(
'https://rocket.chromatic.com/authorize',
expect.objectContaining({ method: 'POST' })
);
expect(result.verificationUrl).toBe(
'https://rocket.chromatic.com/connect/chromaui:addon-visual-tests?code=123123'
);
});

it('keeps the default host when no SSO subdomain is provided', async () => {
fetchMock.mockResolvedValue({
json: async () => ({
device_code: 'device-code',
user_code: '123 123',
verification_uri_complete:
'https://www.chromatic.com/connect/chromaui:addon-visual-tests?code=123123',
expires_in: 300,
interval: 5,
}),
});

const result = await initiateSignin();

expect(fetchMock).toHaveBeenCalledWith(
'https://www.chromatic.com/authorize',
expect.objectContaining({ method: 'POST' })
);
expect(result.verificationUrl).toBe(
'https://www.chromatic.com/connect/chromaui:addon-visual-tests?code=123123'
);
});
});
9 changes: 5 additions & 4 deletions src/utils/requestAccessToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ const betaUserAccessDenied = ({ error_description }: { error_description: string
return error_description === 'Not OAuth beta user';
};

const withSubdomain = (url: string, subdomain?: string) =>
subdomain ? url.replace(/^https:\/\/www\./, `https://${subdomain}.`) : url;

export const initiateSignin = async (subdomain?: string): Promise<TokenExchangeParameters> => {
const verifier = base64URLEncode(seed());
const challenge = base64URLEncode(hexStringToBytes(sha256(verifier)));

const res = await fetch(`${CHROMATIC_BASE_URL}/authorize`, {
const res = await fetch(withSubdomain(`${CHROMATIC_BASE_URL}/authorize`, subdomain), {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
Expand All @@ -58,9 +61,7 @@ export const initiateSignin = async (subdomain?: string): Promise<TokenExchangeP
const { device_code, user_code, verification_uri_complete, expires_in, interval } =
await res.json();

const verificationUrl = subdomain
? verification_uri_complete.replace('https://www', `https://${subdomain}`)
: verification_uri_complete;
const verificationUrl = withSubdomain(verification_uri_complete, subdomain);

return {
expires: Date.now() + expires_in * 1000,
Expand Down