Skip to content

Commit e5f9d32

Browse files
committed
fix(mosaic): let the last copy result decide the create API key copy error
1 parent 4cc46cc commit e5f9d32

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

‎packages/mosaic/src/features/api-keys/__tests__/api-keys-table.feature.test.tsx‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event';
44
import { http, HttpResponse } from 'msw';
55
import { describe, expect, it, vi } from 'vitest';
66

7+
import { deferred } from '../../../__tests__/async';
78
import { openDialog } from '../../../__tests__/feature/dialog';
89
import { type FakeFapiSeed, fapiUrl, holdRequests, serveFapi, worker } from '../../../__tests__/feature/fake-fapi';
910
import {
@@ -501,6 +502,25 @@ describe('APIKeysTable', () => {
501502
expect(screen.getByRole('alertdialog', { name: 'Copy your API Key' })).toBeVisible();
502503
});
503504

505+
it('clears the copy error when an overlapping copy succeeds after one fails', async () => {
506+
const { user } = await renderTable();
507+
const dialog = await openCreate(user);
508+
await fillCreate(user, dialog, 'Deploy', 'Never');
509+
await user.click(within(dialog).getByRole('button', { name: 'Add API Key' }));
510+
await within(dialog).findByRole('textbox', { name: 'API key' });
511+
const first = deferred<void>();
512+
const second = deferred<void>();
513+
vi.spyOn(navigator.clipboard, 'writeText').mockReturnValueOnce(first.promise).mockReturnValueOnce(second.promise);
514+
515+
await user.click(within(dialog).getByRole('button', { name: 'Copy API key' }));
516+
await user.click(within(dialog).getByRole('button', { name: 'Copy API key' }));
517+
first.reject(new Error('blocked'));
518+
await waitFor(() => expect(within(dialog).getByRole('alert')).toHaveTextContent('Could not copy'));
519+
second.resolve();
520+
521+
await waitFor(() => expect(within(dialog).getByRole('alert')).not.toHaveTextContent('Could not copy'));
522+
});
523+
504524
it('closes the secret on Escape after a failed copy', async () => {
505525
const { user } = await renderTable();
506526
const dialog = await openCreate(user);

‎packages/mosaic/src/features/api-keys/create-api-key.controller.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type Event =
4545

4646
const { createMachine, assign } = setup<Context, Event>();
4747

48+
const copied = { target: 'attempted', actions: assign(() => ({ copyFailed: false })) };
49+
const failed = { target: 'attempted', actions: assign(() => ({ copyFailed: true })) };
50+
4851
const machine = createMachine({
4952
id: 'createAPIKey',
5053
initial: 'closed',
@@ -63,13 +66,10 @@ const machine = createMachine({
6366
on: { COPY: 'copying' },
6467
},
6568
copying: {
66-
on: {
67-
COPIED: { target: 'attempted', actions: assign(() => ({ copyFailed: false })) },
68-
COPY_FAILED: { target: 'attempted', actions: assign(() => ({ copyFailed: true })) },
69-
},
69+
on: { COPIED: copied, COPY_FAILED: failed },
7070
},
7171
attempted: {
72-
on: { COPY: 'copying', CLOSE: 'closed' },
72+
on: { COPY: 'copying', COPIED: copied, COPY_FAILED: failed, CLOSE: 'closed' },
7373
},
7474
},
7575
});

0 commit comments

Comments
 (0)