@vertesia/ui 1.5.0-dev.20260713.151751Z → 1.5.0-dev.20260717.131047Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/env/index.d.ts +19 -0
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +6 -0
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +65 -11
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +51 -48
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts +8 -1
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.js +28 -10
- package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +73 -0
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +1 -0
- package/lib/features/document-viewer/UniversalDocumentViewer.js +415 -0
- package/lib/features/document-viewer/UniversalDocumentViewer.js.map +1 -0
- package/lib/features/document-viewer/index.d.ts +2 -0
- package/lib/features/document-viewer/index.d.ts.map +1 -0
- package/lib/features/document-viewer/index.js +2 -0
- package/lib/features/document-viewer/index.js.map +1 -0
- package/lib/features/index.d.ts +1 -0
- package/lib/features/index.d.ts.map +1 -1
- package/lib/features/index.js +1 -0
- package/lib/features/index.js.map +1 -1
- package/lib/features/permissions/UserPermissionsProvider.d.ts +2 -3
- package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
- package/lib/features/permissions/UserPermissionsProvider.js +31 -38
- package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +73 -13
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/i18n/locales/ar.json +2 -0
- package/lib/i18n/locales/de.json +2 -0
- package/lib/i18n/locales/en.json +2 -0
- package/lib/i18n/locales/es.json +2 -0
- package/lib/i18n/locales/fr.json +2 -0
- package/lib/i18n/locales/it.json +2 -0
- package/lib/i18n/locales/ja.json +2 -0
- package/lib/i18n/locales/ko.json +2 -0
- package/lib/i18n/locales/pt.json +2 -0
- package/lib/i18n/locales/ru.json +2 -0
- package/lib/i18n/locales/tr.json +2 -0
- package/lib/i18n/locales/zh-TW.json +2 -0
- package/lib/i18n/locales/zh.json +2 -0
- package/lib/router/HistoryNavigator.d.ts.map +1 -1
- package/lib/router/HistoryNavigator.js +4 -1
- package/lib/router/HistoryNavigator.js.map +1 -1
- package/lib/router/Nav.d.ts.map +1 -1
- package/lib/router/Nav.js +7 -1
- package/lib/router/Nav.js.map +1 -1
- package/lib/router/Router.d.ts.map +1 -1
- package/lib/router/Router.js +19 -4
- package/lib/router/Router.js.map +1 -1
- package/lib/router/path.d.ts +15 -0
- package/lib/router/path.d.ts.map +1 -1
- package/lib/router/path.js +43 -0
- package/lib/router/path.js.map +1 -1
- package/lib/session/UserSession.d.ts +6 -0
- package/lib/session/UserSession.d.ts.map +1 -1
- package/lib/session/UserSession.js +31 -9
- package/lib/session/UserSession.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +111 -49
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +52 -3
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/session/auth/domainRouting.d.ts +25 -0
- package/lib/session/auth/domainRouting.d.ts.map +1 -1
- package/lib/session/auth/domainRouting.js +36 -0
- package/lib/session/auth/domainRouting.js.map +1 -1
- package/lib/shell/login/SignInRestrictedEnvStep.d.ts +1 -1
- package/lib/shell/login/SignInRestrictedEnvStep.js +1 -1
- package/lib/shell/login/SigninScreen.js +9 -1
- package/lib/shell/login/SigninScreen.js.map +1 -1
- package/lib/shell/login/productionUrl.d.ts +0 -14
- package/lib/shell/login/productionUrl.d.ts.map +1 -1
- package/lib/shell/login/productionUrl.js +14 -5
- package/lib/shell/login/productionUrl.js.map +1 -1
- package/lib/vertesia-ui-core.js +3 -3
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +28 -28
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +13 -13
- package/lib/vertesia-ui-router.js +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +2 -2
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/llms.txt +70 -70
- package/package.json +8 -7
- package/src/env/index.ts +24 -0
- package/src/features/agent/chat/ArtifactsTab.tsx +155 -21
- package/src/features/agent/chat/ModernAgentConversation.tsx +53 -49
- package/src/features/agent/chat/hooks/useArtifacts.ts +44 -11
- package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +123 -0
- package/src/features/document-viewer/UniversalDocumentViewer.tsx +746 -0
- package/src/features/document-viewer/index.ts +1 -0
- package/src/features/index.ts +1 -0
- package/src/features/permissions/UserPermissionsProvider.tsx +36 -39
- package/src/features/store/objects/components/ContentOverview.tsx +99 -26
- package/src/i18n/locales/ar.json +2 -0
- package/src/i18n/locales/de.json +2 -0
- package/src/i18n/locales/en.json +2 -0
- package/src/i18n/locales/es.json +2 -0
- package/src/i18n/locales/fr.json +2 -0
- package/src/i18n/locales/it.json +2 -0
- package/src/i18n/locales/ja.json +2 -0
- package/src/i18n/locales/ko.json +2 -0
- package/src/i18n/locales/pt.json +2 -0
- package/src/i18n/locales/ru.json +2 -0
- package/src/i18n/locales/tr.json +2 -0
- package/src/i18n/locales/zh-TW.json +2 -0
- package/src/i18n/locales/zh.json +2 -0
- package/src/router/HistoryNavigator.ts +4 -1
- package/src/router/Nav.tsx +7 -1
- package/src/router/Router.tsx +18 -4
- package/src/router/path.test.ts +87 -0
- package/src/router/path.ts +38 -0
- package/src/session/UserSession.ts +32 -9
- package/src/session/UserSessionProvider.tsx +138 -62
- package/src/session/auth/composable.test.ts +111 -0
- package/src/session/auth/composable.ts +58 -3
- package/src/session/auth/domainRouting.test.ts +28 -1
- package/src/session/auth/domainRouting.ts +38 -0
- package/src/shell/login/SignInRestrictedEnvStep.tsx +1 -1
- package/src/shell/login/SigninScreen.tsx +9 -1
- package/src/shell/login/productionUrl.test.ts +8 -5
- package/src/shell/login/productionUrl.ts +15 -5
|
@@ -925,64 +925,68 @@ function StartWorkflowView({
|
|
|
925
925
|
].join('\n');
|
|
926
926
|
}
|
|
927
927
|
|
|
928
|
+
const newRun = await startWorkflow(messageContent, { tool_approval_mode: toolApprovalMode });
|
|
929
|
+
if (!newRun) {
|
|
930
|
+
setPendingStartMessage(null);
|
|
931
|
+
setPendingStartTimestamp(null);
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
|
|
928
935
|
setPendingStartMessage(messageContent);
|
|
929
936
|
setPendingStartTimestamp(Date.now());
|
|
930
937
|
|
|
931
|
-
const
|
|
932
|
-
if (newRun) {
|
|
933
|
-
const agentId = newRun.agent_run_id;
|
|
934
|
-
|
|
935
|
-
// Upload staged files to the new run's artifact space and signal agent
|
|
936
|
-
const uploadedFiles: string[] = [];
|
|
937
|
-
if (canStageFiles && stagedFiles.length > 0) {
|
|
938
|
-
for (const file of stagedFiles) {
|
|
939
|
-
try {
|
|
940
|
-
const artifactPath = `files/${file.name}`;
|
|
941
|
-
await client.agents.uploadArtifact(agentId, artifactPath, file);
|
|
942
|
-
|
|
943
|
-
// Signal agent that file was uploaded
|
|
944
|
-
await client.agents.sendSignal(agentId, 'FileUploaded', {
|
|
945
|
-
id: `file-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
946
|
-
name: file.name,
|
|
947
|
-
content_type: file.type || 'application/octet-stream',
|
|
948
|
-
reference: `artifact:${artifactPath}`,
|
|
949
|
-
artifact_path: artifactPath,
|
|
950
|
-
} as ConversationFileRef);
|
|
951
|
-
uploadedFiles.push(file.name);
|
|
952
|
-
} catch (uploadErr) {
|
|
953
|
-
console.error(`Failed to upload staged file ${file.name}:`, uploadErr);
|
|
954
|
-
// Continue with other files
|
|
955
|
-
}
|
|
956
|
-
}
|
|
938
|
+
const agentId = newRun.agent_run_id;
|
|
957
939
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
940
|
+
// Upload staged files to the new run's artifact space and signal agent
|
|
941
|
+
const uploadedFiles: string[] = [];
|
|
942
|
+
if (canStageFiles && stagedFiles.length > 0) {
|
|
943
|
+
for (const file of stagedFiles) {
|
|
944
|
+
try {
|
|
945
|
+
const artifactPath = `files/${file.name}`;
|
|
946
|
+
await client.agents.uploadArtifact(agentId, artifactPath, file);
|
|
947
|
+
|
|
948
|
+
// Signal agent that file was uploaded
|
|
949
|
+
await client.agents.sendSignal(agentId, 'FileUploaded', {
|
|
950
|
+
id: `file-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
951
|
+
name: file.name,
|
|
952
|
+
content_type: file.type || 'application/octet-stream',
|
|
953
|
+
reference: `artifact:${artifactPath}`,
|
|
954
|
+
artifact_path: artifactPath,
|
|
955
|
+
} as ConversationFileRef);
|
|
956
|
+
uploadedFiles.push(file.name);
|
|
957
|
+
} catch (uploadErr) {
|
|
958
|
+
console.error(`Failed to upload staged file ${file.name}:`, uploadErr);
|
|
959
|
+
// Continue with other files
|
|
971
960
|
}
|
|
961
|
+
}
|
|
972
962
|
|
|
973
|
-
|
|
963
|
+
// Send a follow-up message to notify the agent that all files are ready
|
|
964
|
+
if (uploadedFiles.length > 0) {
|
|
965
|
+
try {
|
|
966
|
+
await client.agents.sendSignal(agentId, 'UserInput', {
|
|
967
|
+
message: `[Files Ready] All ${uploadedFiles.length} file(s) have been uploaded and are now available: ${uploadedFiles.join(', ')}. You can now process them.`,
|
|
968
|
+
metadata: {
|
|
969
|
+
type: 'files_ready',
|
|
970
|
+
files: uploadedFiles,
|
|
971
|
+
},
|
|
972
|
+
} as UserInputSignal);
|
|
973
|
+
} catch (signalErr) {
|
|
974
|
+
console.error('Failed to send files ready signal:', signalErr);
|
|
975
|
+
}
|
|
974
976
|
}
|
|
975
977
|
|
|
976
|
-
|
|
977
|
-
onAttachmentsSent?.();
|
|
978
|
-
setStartedAgentRunId(agentId);
|
|
979
|
-
setInputValue('');
|
|
980
|
-
toast({
|
|
981
|
-
title: t('agent.agentStarted'),
|
|
982
|
-
status: 'success',
|
|
983
|
-
duration: 3000,
|
|
984
|
-
});
|
|
978
|
+
setStagedFiles([]);
|
|
985
979
|
}
|
|
980
|
+
|
|
981
|
+
// Clear attachments after successful start
|
|
982
|
+
onAttachmentsSent?.();
|
|
983
|
+
setStartedAgentRunId(agentId);
|
|
984
|
+
setInputValue('');
|
|
985
|
+
toast({
|
|
986
|
+
title: t('agent.agentStarted'),
|
|
987
|
+
status: 'success',
|
|
988
|
+
duration: 3000,
|
|
989
|
+
});
|
|
986
990
|
} catch (err: unknown) {
|
|
987
991
|
setPendingStartMessage(null);
|
|
988
992
|
setPendingStartTimestamp(null);
|
|
@@ -15,14 +15,31 @@ export interface ArtifactTreeNode {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// ---------------------------------------------------------------------------
|
|
18
|
-
//
|
|
18
|
+
// System artifacts — agent execution internals (tool I/O hydration,
|
|
19
|
+
// conversation snapshots, process state, archives). Hidden by default and
|
|
20
|
+
// revealed via the "Show system files" toggle.
|
|
19
21
|
// ---------------------------------------------------------------------------
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
// Matched against the run-relative path: any path with one of these directory
|
|
24
|
+
// segments is agent scaffolding rather than a user-facing output.
|
|
25
|
+
const SYSTEM_DIR_PATTERN = /(^|\/)(tool-inputs|tool-results|archive)(\/|$)/;
|
|
26
|
+
const SYSTEM_PROCESS_PATTERN = /(^|\/)process\/(history|state)(\/|$)/;
|
|
27
|
+
|
|
28
|
+
// Matched against the file basename.
|
|
29
|
+
const SYSTEM_BASENAME_PATTERNS = [
|
|
30
|
+
/conversation\.json$/, // conversation.json, <id>-conversation.json
|
|
31
|
+
/^conversation-checkpoint-\d+\.json$/,
|
|
32
|
+
/^tools\.json$/,
|
|
33
|
+
/^tool-input-refs\.json$/,
|
|
34
|
+
/^toolu[_-]/i, // per-tool-use input/result hydration payloads
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
export function isSystemArtifact(relativePath: string): boolean {
|
|
38
|
+
if (SYSTEM_DIR_PATTERN.test(relativePath) || SYSTEM_PROCESS_PATTERN.test(relativePath)) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
24
41
|
const basename = relativePath.split('/').pop() ?? relativePath;
|
|
25
|
-
return
|
|
42
|
+
return SYSTEM_BASENAME_PATTERNS.some((re) => re.test(basename));
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
// ---------------------------------------------------------------------------
|
|
@@ -88,15 +105,26 @@ function stripToRelativePath(fullPath: string, runId: string): string {
|
|
|
88
105
|
// ---------------------------------------------------------------------------
|
|
89
106
|
|
|
90
107
|
export interface UseArtifactsResult {
|
|
108
|
+
/** Tree of the currently visible files (respects `showSystem`). */
|
|
91
109
|
tree: ArtifactTreeNode[];
|
|
110
|
+
/** Currently visible files (respects `showSystem`). */
|
|
92
111
|
flatFiles: string[];
|
|
112
|
+
/** Total number of artifacts in the run, including system files. */
|
|
113
|
+
totalCount: number;
|
|
114
|
+
/** Number of system files currently hidden (0 when `showSystem` is true). */
|
|
115
|
+
systemHiddenCount: number;
|
|
93
116
|
isLoading: boolean;
|
|
94
117
|
error: string | null;
|
|
95
118
|
refresh: () => void;
|
|
96
119
|
}
|
|
97
120
|
|
|
98
|
-
export function useArtifacts(
|
|
99
|
-
|
|
121
|
+
export function useArtifacts(
|
|
122
|
+
client: VertesiaClient,
|
|
123
|
+
runId: string | undefined,
|
|
124
|
+
refreshKey = 0,
|
|
125
|
+
showSystem = false,
|
|
126
|
+
): UseArtifactsResult {
|
|
127
|
+
const [allFiles, setAllFiles] = useState<string[]>([]);
|
|
100
128
|
const [isLoading, setIsLoading] = useState(false);
|
|
101
129
|
const [error, setError] = useState<string | null>(null);
|
|
102
130
|
const [manualRefreshKey, setManualRefreshKey] = useState(0);
|
|
@@ -113,13 +141,13 @@ export function useArtifacts(client: VertesiaClient, runId: string | undefined,
|
|
|
113
141
|
const paths = await client.files.listArtifacts(runId);
|
|
114
142
|
if (fetchId !== fetchIdRef.current) return; // stale
|
|
115
143
|
|
|
116
|
-
const relatives = paths.map((p) => stripToRelativePath(p, runId)).filter((p) => p
|
|
144
|
+
const relatives = paths.map((p) => stripToRelativePath(p, runId)).filter((p) => !!p);
|
|
117
145
|
|
|
118
|
-
|
|
146
|
+
setAllFiles(relatives);
|
|
119
147
|
} catch (err) {
|
|
120
148
|
if (fetchId !== fetchIdRef.current) return;
|
|
121
149
|
setError(err instanceof Error ? err.message : 'Failed to list artifacts');
|
|
122
|
-
|
|
150
|
+
setAllFiles([]);
|
|
123
151
|
} finally {
|
|
124
152
|
if (fetchId === fetchIdRef.current) {
|
|
125
153
|
setIsLoading(false);
|
|
@@ -133,11 +161,16 @@ export function useArtifacts(client: VertesiaClient, runId: string | undefined,
|
|
|
133
161
|
void fetchArtifacts();
|
|
134
162
|
}, [fetchArtifacts, refreshKey, manualRefreshKey]);
|
|
135
163
|
|
|
164
|
+
const flatFiles = useMemo(
|
|
165
|
+
() => (showSystem ? allFiles : allFiles.filter((p) => !isSystemArtifact(p))),
|
|
166
|
+
[allFiles, showSystem],
|
|
167
|
+
);
|
|
136
168
|
const tree = useMemo(() => buildTree(flatFiles), [flatFiles]);
|
|
169
|
+
const systemHiddenCount = allFiles.length - flatFiles.length;
|
|
137
170
|
|
|
138
171
|
const refresh = useCallback(() => {
|
|
139
172
|
setManualRefreshKey((k) => k + 1);
|
|
140
173
|
}, []);
|
|
141
174
|
|
|
142
|
-
return { tree, flatFiles, isLoading, error, refresh };
|
|
175
|
+
return { tree, flatFiles, totalCount: allFiles.length, systemHiddenCount, isLoading, error, refresh };
|
|
143
176
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { renderWithProviders } from '../../__tests__/test-utils.js';
|
|
4
|
+
|
|
5
|
+
const { getArtifactDownloadUrl, getDownloadUrl } = vi.hoisted(() => ({
|
|
6
|
+
getArtifactDownloadUrl: vi.fn(),
|
|
7
|
+
getDownloadUrl: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock('../pdf-viewer/SimplePdfViewer.js', () => ({
|
|
11
|
+
SimplePdfViewer: () => <div data-testid="pdf-viewer" />,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock('@vertesia/ui/session', () => ({
|
|
15
|
+
useUserSession: () => ({
|
|
16
|
+
client: {
|
|
17
|
+
files: {
|
|
18
|
+
getArtifactDownloadUrl,
|
|
19
|
+
getDownloadUrl,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
import { UniversalDocumentViewer } from './UniversalDocumentViewer';
|
|
26
|
+
|
|
27
|
+
describe('UniversalDocumentViewer TSX sandbox preview', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
getArtifactDownloadUrl.mockImplementation(
|
|
31
|
+
async (_runId: string, path: string, _disposition: 'inline' | 'attachment') => ({
|
|
32
|
+
url: `https://signed.example/${encodeURIComponent(path)}`,
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
getDownloadUrl.mockImplementation(
|
|
36
|
+
async (path: string, _fileName?: string, _disposition?: 'inline' | 'attachment') => ({
|
|
37
|
+
url: `https://signed.example/${encodeURIComponent(path)}`,
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
vi.stubGlobal(
|
|
41
|
+
'fetch',
|
|
42
|
+
vi.fn(async (url: string) => {
|
|
43
|
+
const decodedUrl = decodeURIComponent(url);
|
|
44
|
+
const body = decodedUrl.endsWith('.render.json')
|
|
45
|
+
? JSON.stringify({
|
|
46
|
+
ok: true,
|
|
47
|
+
source_artifact: 'files/mockups/Dashboard.tsx',
|
|
48
|
+
screenshot_artifact: 'files/mockups/Dashboard.png',
|
|
49
|
+
rendered_at: '2026-06-03T12:00:00.000Z',
|
|
50
|
+
viewport: { width: 1440, height: 900 },
|
|
51
|
+
dependencies_reused: true,
|
|
52
|
+
status: 200,
|
|
53
|
+
timings_ms: { total_before_cleanup: 11481 },
|
|
54
|
+
})
|
|
55
|
+
: 'export default function Dashboard() { return <main>Dashboard</main>; }';
|
|
56
|
+
return {
|
|
57
|
+
ok: true,
|
|
58
|
+
statusText: 'OK',
|
|
59
|
+
text: async () => body,
|
|
60
|
+
};
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('renders a sibling sandbox PNG preview for TSX artifacts without executing source in Studio', async () => {
|
|
66
|
+
renderWithProviders(
|
|
67
|
+
<UniversalDocumentViewer
|
|
68
|
+
source={{
|
|
69
|
+
fileName: 'Dashboard.tsx',
|
|
70
|
+
contentType: 'text/typescript',
|
|
71
|
+
artifact: {
|
|
72
|
+
runId: 'agent-run-1',
|
|
73
|
+
path: 'files/mockups/Dashboard.tsx',
|
|
74
|
+
},
|
|
75
|
+
}}
|
|
76
|
+
/>,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await screen.findByText('PNG preview');
|
|
80
|
+
const image = screen.getByAltText('Dashboard.tsx sandbox render') as HTMLImageElement;
|
|
81
|
+
expect(image.getAttribute('src')).toBe('https://signed.example/files%2Fmockups%2FDashboard.png');
|
|
82
|
+
expect(screen.getByText('deps reused')).toBeTruthy();
|
|
83
|
+
expect(screen.getByText('Total 11 s')).toBeTruthy();
|
|
84
|
+
expect(screen.getByText(/export default function Dashboard/)).toBeTruthy();
|
|
85
|
+
|
|
86
|
+
await waitFor(() => {
|
|
87
|
+
expect(getArtifactDownloadUrl).toHaveBeenCalledWith(
|
|
88
|
+
'agent-run-1',
|
|
89
|
+
'files/mockups/Dashboard.render.json',
|
|
90
|
+
'inline',
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
expect(getArtifactDownloadUrl).toHaveBeenCalledWith('agent-run-1', 'files/mockups/Dashboard.png', 'inline');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('resolves copied render metadata relative to app design storage paths', async () => {
|
|
97
|
+
renderWithProviders(
|
|
98
|
+
<UniversalDocumentViewer
|
|
99
|
+
source={{
|
|
100
|
+
fileName: 'Dashboard.tsx',
|
|
101
|
+
contentType: 'text/typescript',
|
|
102
|
+
sourcePath: 'apps/store-health/designs/design-1/artifacts/files/mockups/Dashboard.tsx',
|
|
103
|
+
}}
|
|
104
|
+
/>,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
await screen.findByText('PNG preview');
|
|
108
|
+
const image = screen.getByAltText('Dashboard.tsx sandbox render') as HTMLImageElement;
|
|
109
|
+
expect(image.getAttribute('src')).toBe(
|
|
110
|
+
'https://signed.example/apps%2Fstore-health%2Fdesigns%2Fdesign-1%2Fartifacts%2Ffiles%2Fmockups%2FDashboard.png',
|
|
111
|
+
);
|
|
112
|
+
expect(getDownloadUrl).toHaveBeenCalledWith(
|
|
113
|
+
'apps/store-health/designs/design-1/artifacts/files/mockups/Dashboard.render.json',
|
|
114
|
+
'Dashboard.render.json',
|
|
115
|
+
'inline',
|
|
116
|
+
);
|
|
117
|
+
expect(getDownloadUrl).toHaveBeenCalledWith(
|
|
118
|
+
'apps/store-health/designs/design-1/artifacts/files/mockups/Dashboard.png',
|
|
119
|
+
'Dashboard.png',
|
|
120
|
+
'inline',
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
});
|