@@ -5,6 +5,8 @@ import { expect, test } from '@playwright/test';
55 *
66 * Uses collection "e2e-audit" and creates an entity via the API in beforeAll so
77 * at least one audit entry exists when the log page is loaded.
8+ *
9+ * Uses relative URLs so the baseURL from the active Playwright config applies.
810 */
911
1012const COLLECTION_NAME = 'e2e-audit' ;
@@ -13,41 +15,35 @@ const ENTITY_ID = 'audit-entity-001';
1315test . describe ( 'Audit Log' , ( ) => {
1416 test . beforeAll ( async ( { request } ) => {
1517 // Create collection.
16- const collResp = await request . post (
17- `http://localhost:4170/collections/${ COLLECTION_NAME } ` ,
18- {
19- data : {
20- schema : {
21- description : null ,
22- version : 1 ,
23- entity_schema : { type : 'object' , properties : { } } ,
24- link_types : { } ,
25- } ,
26- actor : 'e2e-test' ,
18+ const collResp = await request . post ( `/collections/${ COLLECTION_NAME } ` , {
19+ data : {
20+ schema : {
21+ description : null ,
22+ version : 1 ,
23+ entity_schema : { type : 'object' , properties : { } } ,
24+ link_types : { } ,
2725 } ,
26+ actor : 'e2e-test' ,
2827 } ,
29- ) ;
28+ } ) ;
3029 expect ( [ 201 , 409 ] ) . toContain ( collResp . status ( ) ) ;
3130
3231 // Create an entity so there is an audit entry to show.
33- const entityResp = await request . post (
34- `http://localhost:4170/entities/${ COLLECTION_NAME } /${ ENTITY_ID } ` ,
35- {
36- data : { data : { note : 'audit test' } , actor : 'e2e-test' } ,
37- } ,
38- ) ;
32+ const entityResp = await request . post ( `/entities/${ COLLECTION_NAME } /${ ENTITY_ID } ` , {
33+ data : { data : { note : 'audit test' } , actor : 'e2e-test' } ,
34+ } ) ;
3935 expect ( [ 201 , 409 ] ) . toContain ( entityResp . status ( ) ) ;
4036 } ) ;
4137
4238 test ( 'Audit Log heading is visible' , async ( { page } ) => {
43- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
39+ await page . goto ( '/ui/audit' ) ;
4440 await page . waitForLoadState ( 'networkidle' ) ;
4541
4642 await expect ( page . getByRole ( 'heading' , { name : 'Audit Log' } ) ) . toBeVisible ( { timeout : 15000 } ) ;
4743 } ) ;
4844
4945 test ( 'audit log page has filter controls' , async ( { page } ) => {
50- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
46+ await page . goto ( '/ui/audit' ) ;
5147 await page . waitForLoadState ( 'networkidle' ) ;
5248
5349 await expect ( page . getByPlaceholder ( 'All collections' ) ) . toBeVisible ( { timeout : 15000 } ) ;
@@ -56,7 +52,7 @@ test.describe('Audit Log', () => {
5652 } ) ;
5753
5854 test ( 'audit log contains entries after entity creation' , async ( { page } ) => {
59- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
55+ await page . goto ( '/ui/audit' ) ;
6056 await page . waitForLoadState ( 'networkidle' ) ;
6157
6258 // Wait for the "Recent Entries" panel to load (loading spinner disappears).
@@ -75,7 +71,7 @@ test.describe('Audit Log', () => {
7571 } ) ;
7672
7773 test ( 'clicking an audit row shows entry detail' , async ( { page } ) => {
78- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
74+ await page . goto ( '/ui/audit' ) ;
7975 await page . waitForLoadState ( 'networkidle' ) ;
8076
8177 const recentPanel = page . locator ( 'section.panel' ) . filter ( { hasText : 'Recent Entries' } ) ;
@@ -90,7 +86,6 @@ test.describe('Audit Log', () => {
9086 await firstRow . click ( ) ;
9187
9288 // The detail panel is the second panel in the two-column grid.
93- // The audit page auto-selects the first entry, so the heading shows "Entry #N".
9489 const detailPanel = page . locator ( '.two-column section.panel' ) . nth ( 1 ) ;
9590 await expect ( detailPanel . getByRole ( 'heading' , { name : / E n t r y # \d + / } ) ) . toBeVisible ( {
9691 timeout : 15000 ,
@@ -103,37 +98,28 @@ test.describe('Audit Log', () => {
10398} ) ;
10499
105100test . describe ( 'Audit Log filtering' , ( ) => {
106- // The beforeAll from "Audit Log" already runs when tests execute in order,
107- // but we need our own to guarantee the collection and entity exist regardless
108- // of test ordering.
109101 test . beforeAll ( async ( { request } ) => {
110- const collResp = await request . post (
111- `http://localhost:4170/collections/${ COLLECTION_NAME } ` ,
112- {
113- data : {
114- schema : {
115- description : null ,
116- version : 1 ,
117- entity_schema : { type : 'object' , properties : { } } ,
118- link_types : { } ,
119- } ,
120- actor : 'e2e-test' ,
102+ const collResp = await request . post ( `/collections/${ COLLECTION_NAME } ` , {
103+ data : {
104+ schema : {
105+ description : null ,
106+ version : 1 ,
107+ entity_schema : { type : 'object' , properties : { } } ,
108+ link_types : { } ,
121109 } ,
110+ actor : 'e2e-test' ,
122111 } ,
123- ) ;
112+ } ) ;
124113 expect ( [ 201 , 409 ] ) . toContain ( collResp . status ( ) ) ;
125114
126- const entityResp = await request . post (
127- `http://localhost:4170/entities/${ COLLECTION_NAME } /${ ENTITY_ID } ` ,
128- {
129- data : { data : { note : 'audit filter test' } , actor : 'e2e-test' } ,
130- } ,
131- ) ;
115+ const entityResp = await request . post ( `/entities/${ COLLECTION_NAME } /${ ENTITY_ID } ` , {
116+ data : { data : { note : 'audit filter test' } , actor : 'e2e-test' } ,
117+ } ) ;
132118 expect ( [ 201 , 409 ] ) . toContain ( entityResp . status ( ) ) ;
133119 } ) ;
134120
135121 test ( 'audit table shows all expected columns' , async ( { page } ) => {
136- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
122+ await page . goto ( '/ui/audit' ) ;
137123 await page . waitForLoadState ( 'networkidle' ) ;
138124
139125 const recentPanel = page . locator ( 'section.panel' ) . filter ( { hasText : 'Recent Entries' } ) ;
@@ -152,7 +138,7 @@ test.describe('Audit Log filtering', () => {
152138 } ) ;
153139
154140 test ( 'filter by collection narrows results' , async ( { page } ) => {
155- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
141+ await page . goto ( '/ui/audit' ) ;
156142 await page . waitForLoadState ( 'networkidle' ) ;
157143
158144 const recentPanel = page . locator ( 'section.panel' ) . filter ( { hasText : 'Recent Entries' } ) ;
@@ -162,11 +148,16 @@ test.describe('Audit Log filtering', () => {
162148
163149 // Apply a collection filter for "e2e-audit".
164150 await page . getByPlaceholder ( 'All collections' ) . fill ( COLLECTION_NAME ) ;
151+ // Wait for the network response from the filter request, then check results.
152+ const filterResponsePromise = page . waitForResponse (
153+ ( resp ) => resp . url ( ) . includes ( '/audit/query' ) && resp . status ( ) === 200 ,
154+ ) ;
165155 await page . getByRole ( 'button' , { name : 'Apply Filters' } ) . click ( ) ;
166- await page . waitForLoadState ( 'networkidle' ) ;
156+ await filterResponsePromise ;
167157
168158 // All visible Collection cells (3rd column) should contain "e2e-audit".
169159 const collectionCells = auditTable . locator ( 'tbody tr td:nth-child(3)' ) ;
160+ await expect ( collectionCells . first ( ) ) . toBeVisible ( { timeout : 15000 } ) ;
170161 const count = await collectionCells . count ( ) ;
171162 expect ( count ) . toBeGreaterThan ( 0 ) ;
172163 for ( let i = 0 ; i < count ; i ++ ) {
@@ -175,23 +166,25 @@ test.describe('Audit Log filtering', () => {
175166
176167 // Negative test: filter by a non-existent collection name.
177168 await page . getByPlaceholder ( 'All collections' ) . fill ( 'zzznonexistent' ) ;
169+ const emptyResponsePromise = page . waitForResponse (
170+ ( resp ) => resp . url ( ) . includes ( '/audit/query' ) && resp . status ( ) === 200 ,
171+ ) ;
178172 await page . getByRole ( 'button' , { name : 'Apply Filters' } ) . click ( ) ;
179- await page . waitForLoadState ( 'networkidle' ) ;
173+ await emptyResponsePromise ;
180174
181175 await expect (
182176 page . getByText ( 'No audit entries matched the current filters.' ) ,
183177 ) . toBeVisible ( { timeout : 15000 } ) ;
184178 } ) ;
185179
186180 test ( 'filter by actor shows entries for that actor' , async ( { page } ) => {
187- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
181+ await page . goto ( '/ui/audit' ) ;
188182 await page . waitForLoadState ( 'networkidle' ) ;
189183
190184 const recentPanel = page . locator ( 'section.panel' ) . filter ( { hasText : 'Recent Entries' } ) ;
191185 await expect ( recentPanel ) . toBeVisible ( { timeout : 15000 } ) ;
192186
193- // In --no-auth mode all entries are recorded with actor="anonymous" regardless of
194- // the actor field sent in the request body.
187+ // In --no-auth mode all entries are recorded with actor="anonymous".
195188 await page . getByPlaceholder ( 'All actors' ) . fill ( 'anonymous' ) ;
196189 await page . getByRole ( 'button' , { name : 'Apply Filters' } ) . click ( ) ;
197190 await page . waitForLoadState ( 'networkidle' ) ;
@@ -209,7 +202,7 @@ test.describe('Audit Log filtering', () => {
209202 } ) ;
210203
211204 test ( 'clear filters restores all entries' , async ( { page } ) => {
212- await page . goto ( 'http://localhost:4170 /ui/audit' ) ;
205+ await page . goto ( '/ui/audit' ) ;
213206 await page . waitForLoadState ( 'networkidle' ) ;
214207
215208 const recentPanel = page . locator ( 'section.panel' ) . filter ( { hasText : 'Recent Entries' } ) ;
0 commit comments