@lowdefy/e2e-utils 0.0.0-experimental-20260720072521 → 0.0.0-experimental-20260720135014
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/dist/config.js +4 -1
- package/dist/core/api.js +29 -2
- package/dist/core/index.js +5 -5
- package/dist/core/navigation.js +6 -2
- package/dist/core/requests.js +31 -2
- package/dist/core/state.js +17 -7
- package/dist/core/url.js +19 -2
- package/dist/core/validation.js +50 -2
- package/dist/fixtures/index.js +1 -16
- package/dist/index.js +11 -22
- package/dist/proxy/createBlockHelper.js +1 -1
- package/dist/proxy/createPageManager.js +15 -25
- package/package.json +6 -7
- package/dist/assertions/api.js +0 -43
- package/dist/assertions/index.js +0 -20
- package/dist/assertions/navigation.js +0 -19
- package/dist/assertions/requests.js +0 -45
- package/dist/assertions/state.js +0 -26
- package/dist/assertions/url.js +0 -32
- package/dist/assertions/validation.js +0 -64
- package/dist/runtime.js +0 -32
package/dist/config.js
CHANGED
|
@@ -94,7 +94,10 @@ function createMultiAppConfig({ apps = [], commandPrefix = '', testDir = 'e2e',
|
|
|
94
94
|
url: `http://localhost:${app.port}/api/auth/session`,
|
|
95
95
|
reuseExistingServer: true,
|
|
96
96
|
timeout,
|
|
97
|
-
cwd: app.appDir
|
|
97
|
+
cwd: app.appDir,
|
|
98
|
+
env: {
|
|
99
|
+
NEXT_PUBLIC_LOWDEFY_E2E: 'true'
|
|
100
|
+
}
|
|
98
101
|
};
|
|
99
102
|
});
|
|
100
103
|
return defineConfig({
|
package/dist/core/api.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
async function getApiState(page, endpointId) {
|
|
16
17
|
return page.evaluate((id)=>{
|
|
17
18
|
const lowdefy = window.lowdefy;
|
|
18
19
|
return lowdefy?.apiResponses?.[id]?.[0];
|
|
@@ -22,4 +23,30 @@ async function getApiResponse(page, { endpointId }) {
|
|
|
22
23
|
const state = await getApiState(page, endpointId);
|
|
23
24
|
return state?.response;
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
async function expectApi(page, { endpointId, loading, response, payload, timeout = 30000 }) {
|
|
27
|
+
if (loading !== undefined) {
|
|
28
|
+
await expect.poll(async ()=>{
|
|
29
|
+
const state = await getApiState(page, endpointId);
|
|
30
|
+
return state?.loading;
|
|
31
|
+
}, {
|
|
32
|
+
timeout
|
|
33
|
+
}).toBe(loading);
|
|
34
|
+
}
|
|
35
|
+
if (response !== undefined) {
|
|
36
|
+
await expect.poll(async ()=>{
|
|
37
|
+
const state = await getApiState(page, endpointId);
|
|
38
|
+
return state?.response;
|
|
39
|
+
}, {
|
|
40
|
+
timeout
|
|
41
|
+
}).toEqual(expect.objectContaining(response));
|
|
42
|
+
}
|
|
43
|
+
if (payload !== undefined) {
|
|
44
|
+
await expect.poll(async ()=>{
|
|
45
|
+
const state = await getApiState(page, endpointId);
|
|
46
|
+
return state?.payload;
|
|
47
|
+
}, {
|
|
48
|
+
timeout
|
|
49
|
+
}).toEqual(expect.objectContaining(payload));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export { getApiState, getApiResponse, expectApi };
|
package/dist/core/index.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ export { getBlock } from './locators.js';
|
|
16
|
-
export { goto, waitForReady, waitForPage } from './navigation.js';
|
|
17
|
-
export { getRequestState, getRequestResponse } from './requests.js';
|
|
18
|
-
export { getState, getBlockState, setState } from './state.js';
|
|
19
|
-
export { getValidation } from './validation.js';
|
|
20
|
-
export { setUrlQuery } from './url.js';
|
|
16
|
+
export { goto, waitForReady, expectNavigation, waitForPage } from './navigation.js';
|
|
17
|
+
export { getRequestState, getRequestResponse, expectRequest } from './requests.js';
|
|
18
|
+
export { getState, getBlockState, setState, expectState } from './state.js';
|
|
19
|
+
export { getValidation, expectValidationError, expectValidationWarning, expectValidationSuccess } from './validation.js';
|
|
20
|
+
export { expectUrl, expectUrlQuery, setUrlQuery } from './url.js';
|
package/dist/core/navigation.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
async function waitForReady(page) {
|
|
16
17
|
// Wait for Lowdefy client to initialize (context exists)
|
|
17
18
|
// Context key is "page:{pageId}" not just pageId
|
|
18
19
|
await page.waitForFunction(()=>{
|
|
@@ -31,10 +32,13 @@ async function goto(page, path) {
|
|
|
31
32
|
});
|
|
32
33
|
await waitForReady(page);
|
|
33
34
|
}
|
|
35
|
+
async function expectNavigation(page, urlPattern) {
|
|
36
|
+
await expect(page).toHaveURL(urlPattern);
|
|
37
|
+
}
|
|
34
38
|
async function waitForPage(page, path) {
|
|
35
39
|
await page.waitForURL(path, {
|
|
36
40
|
waitUntil: 'domcontentloaded'
|
|
37
41
|
});
|
|
38
42
|
await waitForReady(page);
|
|
39
43
|
}
|
|
40
|
-
export { goto, waitForReady, waitForPage };
|
|
44
|
+
export { goto, waitForReady, expectNavigation, waitForPage };
|
package/dist/core/requests.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
async function getRequestState(page, requestId) {
|
|
16
17
|
return page.evaluate((reqId)=>{
|
|
17
18
|
const lowdefy = window.lowdefy;
|
|
18
19
|
const pageId = lowdefy?.pageId;
|
|
@@ -24,4 +25,32 @@ async function getRequestResponse(page, { requestId }) {
|
|
|
24
25
|
const state = await getRequestState(page, requestId);
|
|
25
26
|
return state?.response;
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
async function expectRequest(page, { requestId, loading, response, payload, timeout = 30000 }) {
|
|
29
|
+
if (loading !== undefined) {
|
|
30
|
+
await expect.poll(async ()=>{
|
|
31
|
+
const state = await getRequestState(page, requestId);
|
|
32
|
+
return state?.loading;
|
|
33
|
+
}, {
|
|
34
|
+
timeout
|
|
35
|
+
}).toBe(loading);
|
|
36
|
+
}
|
|
37
|
+
if (response !== undefined) {
|
|
38
|
+
await expect.poll(async ()=>{
|
|
39
|
+
const state = await getRequestState(page, requestId);
|
|
40
|
+
return state?.response;
|
|
41
|
+
}, {
|
|
42
|
+
timeout
|
|
43
|
+
}).toEqual(expect.objectContaining(response));
|
|
44
|
+
}
|
|
45
|
+
// Payload is stored in the request state by the Lowdefy engine.
|
|
46
|
+
// It's the evaluated payload from the request config (client-side).
|
|
47
|
+
if (payload !== undefined) {
|
|
48
|
+
await expect.poll(async ()=>{
|
|
49
|
+
const state = await getRequestState(page, requestId);
|
|
50
|
+
return state?.payload;
|
|
51
|
+
}, {
|
|
52
|
+
timeout
|
|
53
|
+
}).toEqual(expect.objectContaining(payload));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export { getRequestState, getRequestResponse, expectRequest };
|
package/dist/core/state.js
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
import { get } from '@lowdefy/helpers';
|
|
17
|
+
async function getState(page) {
|
|
16
18
|
return page.evaluate(()=>{
|
|
17
19
|
const lowdefy = window.lowdefy;
|
|
18
20
|
const pageId = lowdefy?.pageId;
|
|
@@ -24,18 +26,26 @@ async function getBlockState(page, { blockId }) {
|
|
|
24
26
|
return state?.[blockId];
|
|
25
27
|
}
|
|
26
28
|
async function setState(page, { key, value }) {
|
|
27
|
-
// context.methods.setState does not exist on engine contexts - the engine's
|
|
28
|
-
// action layer (see createSetState.js) writes state via State.set() and then
|
|
29
|
-
// triggers a re-render via context._internal.update().
|
|
30
29
|
await page.evaluate(({ k, v })=>{
|
|
31
30
|
const lowdefy = window.lowdefy;
|
|
32
31
|
const pageId = lowdefy?.pageId;
|
|
33
32
|
const context = lowdefy?.contexts?.[`page:${pageId}`];
|
|
34
|
-
context
|
|
35
|
-
|
|
33
|
+
if (context?.methods?.setState) {
|
|
34
|
+
context.methods.setState({
|
|
35
|
+
[k]: v
|
|
36
|
+
});
|
|
37
|
+
}
|
|
36
38
|
}, {
|
|
37
39
|
k: key,
|
|
38
40
|
v: value
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
|
-
|
|
43
|
+
async function expectState(page, { key, value, timeout = 5000 }) {
|
|
44
|
+
await expect.poll(async ()=>{
|
|
45
|
+
const state = await getState(page);
|
|
46
|
+
return get(state, key);
|
|
47
|
+
}, {
|
|
48
|
+
timeout
|
|
49
|
+
}).toEqual(value);
|
|
50
|
+
}
|
|
51
|
+
export { getState, getBlockState, setState, expectState };
|
package/dist/core/url.js
CHANGED
|
@@ -12,7 +12,24 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
async function expectUrl(page, { url, timeout = 5000 }) {
|
|
17
|
+
if (!url) {
|
|
18
|
+
throw new Error('expectUrl requires a "url" parameter (string or RegExp).');
|
|
19
|
+
}
|
|
20
|
+
await expect(page).toHaveURL(url, {
|
|
21
|
+
timeout
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async function expectUrlQuery(page, { key, value, timeout = 5000 }) {
|
|
25
|
+
await expect.poll(async ()=>{
|
|
26
|
+
const url = new URL(page.url());
|
|
27
|
+
return url.searchParams.get(key);
|
|
28
|
+
}, {
|
|
29
|
+
timeout
|
|
30
|
+
}).toBe(value);
|
|
31
|
+
}
|
|
32
|
+
async function setUrlQuery(page, { key, value }) {
|
|
16
33
|
await page.evaluate(({ k, v })=>{
|
|
17
34
|
const url = new URL(window.location.href);
|
|
18
35
|
if (v === null || v === undefined) {
|
|
@@ -26,4 +43,4 @@
|
|
|
26
43
|
v: value
|
|
27
44
|
});
|
|
28
45
|
}
|
|
29
|
-
export { setUrlQuery };
|
|
46
|
+
export { expectUrl, expectUrlQuery, setUrlQuery };
|
package/dist/core/validation.js
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/
|
|
15
|
+
*/ import { expect } from '@playwright/test';
|
|
16
|
+
async function getValidation(page, blockId) {
|
|
16
17
|
return page.evaluate((id)=>{
|
|
17
18
|
const lowdefy = window.lowdefy;
|
|
18
19
|
const pageId = lowdefy?.pageId;
|
|
@@ -21,4 +22,51 @@
|
|
|
21
22
|
return block?.validationEval?.output;
|
|
22
23
|
}, blockId);
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
+
async function expectValidationStatus(page, { blockId, status, timeout = 5000 }) {
|
|
26
|
+
await expect.poll(async ()=>{
|
|
27
|
+
const validation = await getValidation(page, blockId);
|
|
28
|
+
return validation?.status;
|
|
29
|
+
}, {
|
|
30
|
+
timeout
|
|
31
|
+
}).toBe(status);
|
|
32
|
+
}
|
|
33
|
+
async function expectValidationError(page, { blockId, message, timeout = 5000 }) {
|
|
34
|
+
await expect.poll(async ()=>{
|
|
35
|
+
const validation = await getValidation(page, blockId);
|
|
36
|
+
if (validation?.status !== 'error') return {
|
|
37
|
+
status: validation?.status
|
|
38
|
+
};
|
|
39
|
+
if (message && !validation?.errors?.includes(message)) {
|
|
40
|
+
return {
|
|
41
|
+
errors: validation?.errors
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}, {
|
|
46
|
+
timeout
|
|
47
|
+
}).toBe(true);
|
|
48
|
+
}
|
|
49
|
+
async function expectValidationWarning(page, { blockId, message, timeout = 5000 }) {
|
|
50
|
+
await expect.poll(async ()=>{
|
|
51
|
+
const validation = await getValidation(page, blockId);
|
|
52
|
+
if (validation?.status !== 'warning') return {
|
|
53
|
+
status: validation?.status
|
|
54
|
+
};
|
|
55
|
+
if (message && !validation?.warnings?.includes(message)) {
|
|
56
|
+
return {
|
|
57
|
+
warnings: validation?.warnings
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}, {
|
|
62
|
+
timeout
|
|
63
|
+
}).toBe(true);
|
|
64
|
+
}
|
|
65
|
+
async function expectValidationSuccess(page, { blockId, timeout = 5000 }) {
|
|
66
|
+
await expectValidationStatus(page, {
|
|
67
|
+
blockId,
|
|
68
|
+
status: 'success',
|
|
69
|
+
timeout
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export { getValidation, expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess };
|
package/dist/fixtures/index.js
CHANGED
|
@@ -20,20 +20,6 @@ import createPageManager from '../proxy/createPageManager.js';
|
|
|
20
20
|
import { generateManifest, loadManifest } from '../testPrep/generateManifest.js';
|
|
21
21
|
import { createMockManager, loadStaticMocks } from '../mocking/index.js';
|
|
22
22
|
import { setUserCookie } from '../core/userCookie.js';
|
|
23
|
-
import { expectState } from '../assertions/state.js';
|
|
24
|
-
import { expectRequest } from '../assertions/requests.js';
|
|
25
|
-
import { expectApi } from '../assertions/api.js';
|
|
26
|
-
import { expectUrl, expectUrlQuery } from '../assertions/url.js';
|
|
27
|
-
// The Playwright `expect` implementations createPageManager needs for its
|
|
28
|
-
// `.expect.*` methods - injected here so createPageManager itself (exported from
|
|
29
|
-
// the "./runtime" subpath too) never has to import @playwright/test.
|
|
30
|
-
const assertions = {
|
|
31
|
-
expectState,
|
|
32
|
-
expectRequest,
|
|
33
|
-
expectApi,
|
|
34
|
-
expectUrl,
|
|
35
|
-
expectUrlQuery
|
|
36
|
-
};
|
|
37
23
|
const DEFAULT_BUILD_DIR = '.lowdefy/server/build';
|
|
38
24
|
// Create test with ldf fixture
|
|
39
25
|
export const test = base.extend({
|
|
@@ -163,8 +149,7 @@ export const test = base.extend({
|
|
|
163
149
|
page,
|
|
164
150
|
manifest,
|
|
165
151
|
helperRegistry,
|
|
166
|
-
mockManager
|
|
167
|
-
assertions
|
|
152
|
+
mockManager
|
|
168
153
|
});
|
|
169
154
|
await use(pageManager);
|
|
170
155
|
await mockManager.cleanup();
|
package/dist/index.js
CHANGED
|
@@ -12,32 +12,21 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/ // Core helpers
|
|
15
|
+
*/ // Core helpers
|
|
16
16
|
import { escapeId } from './core/escapeId.js';
|
|
17
17
|
import { getBlock } from './core/locators.js';
|
|
18
|
-
import { goto, waitForReady, waitForPage } from './core/navigation.js';
|
|
19
|
-
import { getRequestState, getRequestResponse } from './core/requests.js';
|
|
20
|
-
import { getState, getBlockState, setState } from './core/state.js';
|
|
21
|
-
import { getValidation } from './core/validation.js';
|
|
22
|
-
import { setUrlQuery } from './core/url.js';
|
|
18
|
+
import { goto, waitForReady, expectNavigation, waitForPage } from './core/navigation.js';
|
|
19
|
+
import { getRequestState, getRequestResponse, expectRequest } from './core/requests.js';
|
|
20
|
+
import { getState, getBlockState, setState, expectState } from './core/state.js';
|
|
21
|
+
import { getValidation, expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess } from './core/validation.js';
|
|
22
|
+
import { expectUrl, expectUrlQuery, setUrlQuery } from './core/url.js';
|
|
23
23
|
export { escapeId };
|
|
24
24
|
export { getBlock };
|
|
25
|
-
export { goto, waitForReady, waitForPage };
|
|
26
|
-
export { getRequestState, getRequestResponse };
|
|
27
|
-
export { getState, getBlockState, setState };
|
|
28
|
-
export { getValidation };
|
|
29
|
-
export { setUrlQuery };
|
|
30
|
-
// Assertions (coupled to @playwright/test)
|
|
31
|
-
import { expectNavigation } from './assertions/navigation.js';
|
|
32
|
-
import { expectRequest } from './assertions/requests.js';
|
|
33
|
-
import { expectState } from './assertions/state.js';
|
|
34
|
-
import { expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess } from './assertions/validation.js';
|
|
35
|
-
import { expectUrl, expectUrlQuery } from './assertions/url.js';
|
|
36
|
-
export { expectNavigation };
|
|
37
|
-
export { expectRequest };
|
|
38
|
-
export { expectState };
|
|
39
|
-
export { expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess };
|
|
40
|
-
export { expectUrl, expectUrlQuery };
|
|
25
|
+
export { goto, waitForReady, expectNavigation, waitForPage };
|
|
26
|
+
export { getRequestState, getRequestResponse, expectRequest };
|
|
27
|
+
export { getState, getBlockState, setState, expectState };
|
|
28
|
+
export { getValidation, expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess };
|
|
29
|
+
export { expectUrl, expectUrlQuery, setUrlQuery };
|
|
41
30
|
// Test prep utilities
|
|
42
31
|
import { generateManifest, loadManifest } from './testPrep/generateManifest.js';
|
|
43
32
|
export { generateManifest, loadManifest };
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { expect } from '@playwright/test';
|
|
16
|
-
import { expectValidationError, expectValidationWarning, expectValidationSuccess } from '../
|
|
16
|
+
import { expectValidationError, expectValidationWarning, expectValidationSuccess } from '../core/validation.js';
|
|
17
17
|
// Each block's e2e helper defines a `locator` function that targets the block element on the page.
|
|
18
18
|
// Two locator patterns exist:
|
|
19
19
|
// - `#${escapeId(blockId)}` — for blocks that render `id={blockId}` on their root DOM element
|
|
@@ -14,26 +14,16 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { getBlock } from '../core/locators.js';
|
|
16
16
|
import { waitForReady, waitForPage } from '../core/navigation.js';
|
|
17
|
-
import { getState, getBlockState, setState } from '../core/state.js';
|
|
18
|
-
import { getRequestState, getRequestResponse } from '../core/requests.js';
|
|
19
|
-
import { getApiState, getApiResponse } from '../core/api.js';
|
|
17
|
+
import { getState, getBlockState, setState, expectState } from '../core/state.js';
|
|
18
|
+
import { getRequestState, getRequestResponse, expectRequest } from '../core/requests.js';
|
|
19
|
+
import { getApiState, getApiResponse, expectApi } from '../core/api.js';
|
|
20
20
|
import { getValidation } from '../core/validation.js';
|
|
21
|
-
import { setUrlQuery } from '../core/url.js';
|
|
21
|
+
import { expectUrl, expectUrlQuery, setUrlQuery } from '../core/url.js';
|
|
22
22
|
import { setUserCookie, clearUserCookie } from '../core/userCookie.js';
|
|
23
23
|
import { get, type } from '@lowdefy/helpers';
|
|
24
24
|
import createBlockMethodProxy from './createBlockMethodProxy.js';
|
|
25
25
|
import resolveTemplateId from './resolveTemplateId.js';
|
|
26
|
-
|
|
27
|
-
// "./runtime" subpath). The Playwright-backed `expect*` functions are injected via
|
|
28
|
-
// `assertions` by the caller - the "./fixtures" ldf fixture wires these automatically.
|
|
29
|
-
function requireAssertion(fn, name) {
|
|
30
|
-
if (type.isUndefined(fn)) {
|
|
31
|
-
throw new Error(`createPageManager: "${name}" assertion is not available on this instance. ` + `Import { ${name} } from "@lowdefy/e2e-utils" and pass it as assertions.${name}, ` + `or use the "@lowdefy/e2e-utils/fixtures" ldf fixture, which wires assertions automatically.`);
|
|
32
|
-
}
|
|
33
|
-
return fn;
|
|
34
|
-
}
|
|
35
|
-
function createPageManager({ page, manifest, helperRegistry, mockManager, assertions = {} }) {
|
|
36
|
-
const { expectState, expectRequest, expectApi, expectUrl, expectUrlQuery } = assertions;
|
|
26
|
+
function createPageManager({ page, manifest, helperRegistry, mockManager }) {
|
|
37
27
|
let currentBlockMap = null;
|
|
38
28
|
let currentPageId = null;
|
|
39
29
|
function ensurePageLoaded() {
|
|
@@ -152,17 +142,17 @@ function createPageManager({ page, manifest, helperRegistry, mockManager, assert
|
|
|
152
142
|
request (requestId) {
|
|
153
143
|
return {
|
|
154
144
|
expect: {
|
|
155
|
-
toFinish: (opts)=>
|
|
145
|
+
toFinish: (opts)=>expectRequest(page, {
|
|
156
146
|
requestId,
|
|
157
147
|
loading: false,
|
|
158
148
|
...opts
|
|
159
149
|
}),
|
|
160
|
-
toHaveResponse: (response, opts)=>
|
|
150
|
+
toHaveResponse: (response, opts)=>expectRequest(page, {
|
|
161
151
|
requestId,
|
|
162
152
|
response,
|
|
163
153
|
...opts
|
|
164
154
|
}),
|
|
165
|
-
toHavePayload: (payload, opts)=>
|
|
155
|
+
toHavePayload: (payload, opts)=>expectRequest(page, {
|
|
166
156
|
requestId,
|
|
167
157
|
payload,
|
|
168
158
|
...opts
|
|
@@ -178,17 +168,17 @@ function createPageManager({ page, manifest, helperRegistry, mockManager, assert
|
|
|
178
168
|
api (endpointId) {
|
|
179
169
|
return {
|
|
180
170
|
expect: {
|
|
181
|
-
toFinish: (opts)=>
|
|
171
|
+
toFinish: (opts)=>expectApi(page, {
|
|
182
172
|
endpointId,
|
|
183
173
|
loading: false,
|
|
184
174
|
...opts
|
|
185
175
|
}),
|
|
186
|
-
toHaveResponse: (response, opts)=>
|
|
176
|
+
toHaveResponse: (response, opts)=>expectApi(page, {
|
|
187
177
|
endpointId,
|
|
188
178
|
response,
|
|
189
179
|
...opts
|
|
190
180
|
}),
|
|
191
|
-
toHavePayload: (payload, opts)=>
|
|
181
|
+
toHavePayload: (payload, opts)=>expectApi(page, {
|
|
192
182
|
endpointId,
|
|
193
183
|
payload,
|
|
194
184
|
...opts
|
|
@@ -215,7 +205,7 @@ function createPageManager({ page, manifest, helperRegistry, mockManager, assert
|
|
|
215
205
|
})
|
|
216
206
|
},
|
|
217
207
|
expect: {
|
|
218
|
-
toBe: (value, opts)=>
|
|
208
|
+
toBe: (value, opts)=>expectState(page, {
|
|
219
209
|
key,
|
|
220
210
|
value,
|
|
221
211
|
...opts
|
|
@@ -228,11 +218,11 @@ function createPageManager({ page, manifest, helperRegistry, mockManager, assert
|
|
|
228
218
|
url () {
|
|
229
219
|
return {
|
|
230
220
|
expect: {
|
|
231
|
-
toBe: (path, opts)=>
|
|
221
|
+
toBe: (path, opts)=>expectUrl(page, {
|
|
232
222
|
url: path,
|
|
233
223
|
...opts
|
|
234
224
|
}),
|
|
235
|
-
toMatch: (pattern, opts)=>
|
|
225
|
+
toMatch: (pattern, opts)=>expectUrl(page, {
|
|
236
226
|
url: pattern,
|
|
237
227
|
...opts
|
|
238
228
|
})
|
|
@@ -250,7 +240,7 @@ function createPageManager({ page, manifest, helperRegistry, mockManager, assert
|
|
|
250
240
|
})
|
|
251
241
|
},
|
|
252
242
|
expect: {
|
|
253
|
-
toBe: (value, opts)=>
|
|
243
|
+
toBe: (value, opts)=>expectUrlQuery(page, {
|
|
254
244
|
key,
|
|
255
245
|
value,
|
|
256
246
|
...opts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/e2e-utils",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-20260720135014",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Lowdefy E2E Testing Utilities for Playwright",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -30,23 +30,22 @@
|
|
|
30
30
|
"exports": {
|
|
31
31
|
".": "./dist/index.js",
|
|
32
32
|
"./config": "./dist/config.js",
|
|
33
|
-
"./fixtures": "./dist/fixtures/index.js"
|
|
34
|
-
"./runtime": "./dist/runtime.js"
|
|
33
|
+
"./fixtures": "./dist/fixtures/index.js"
|
|
35
34
|
},
|
|
36
35
|
"files": [
|
|
37
36
|
"dist/*"
|
|
38
37
|
],
|
|
39
38
|
"dependencies": {
|
|
40
|
-
"@lowdefy/helpers": "0.0.0-experimental-
|
|
39
|
+
"@lowdefy/helpers": "0.0.0-experimental-20260720135014",
|
|
41
40
|
"js-yaml": "4.1.0",
|
|
42
41
|
"prompts": "2.4.2"
|
|
43
42
|
},
|
|
44
43
|
"peerDependencies": {
|
|
45
|
-
"@playwright/test": "1.
|
|
44
|
+
"@playwright/test": "1.50.1"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|
|
48
|
-
"@swc/cli": "0.8.
|
|
49
|
-
"@swc/core": "1.15.
|
|
47
|
+
"@swc/cli": "0.8.0",
|
|
48
|
+
"@swc/core": "1.15.18",
|
|
50
49
|
"copyfiles": "2.4.1",
|
|
51
50
|
"jest": "28.1.3"
|
|
52
51
|
},
|
package/dist/assertions/api.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
import { getApiState } from '../core/api.js';
|
|
17
|
-
async function expectApi(page, { endpointId, loading, response, payload, timeout = 30000 }) {
|
|
18
|
-
if (loading !== undefined) {
|
|
19
|
-
await expect.poll(async ()=>{
|
|
20
|
-
const state = await getApiState(page, endpointId);
|
|
21
|
-
return state?.loading;
|
|
22
|
-
}, {
|
|
23
|
-
timeout
|
|
24
|
-
}).toBe(loading);
|
|
25
|
-
}
|
|
26
|
-
if (response !== undefined) {
|
|
27
|
-
await expect.poll(async ()=>{
|
|
28
|
-
const state = await getApiState(page, endpointId);
|
|
29
|
-
return state?.response;
|
|
30
|
-
}, {
|
|
31
|
-
timeout
|
|
32
|
-
}).toEqual(expect.objectContaining(response));
|
|
33
|
-
}
|
|
34
|
-
if (payload !== undefined) {
|
|
35
|
-
await expect.poll(async ()=>{
|
|
36
|
-
const state = await getApiState(page, endpointId);
|
|
37
|
-
return state?.payload;
|
|
38
|
-
}, {
|
|
39
|
-
timeout
|
|
40
|
-
}).toEqual(expect.objectContaining(payload));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export { expectApi };
|
package/dist/assertions/index.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ export { expectState } from './state.js';
|
|
16
|
-
export { expectRequest } from './requests.js';
|
|
17
|
-
export { expectApi } from './api.js';
|
|
18
|
-
export { expectNavigation } from './navigation.js';
|
|
19
|
-
export { expectUrl, expectUrlQuery } from './url.js';
|
|
20
|
-
export { expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess } from './validation.js';
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
async function expectNavigation(page, urlPattern) {
|
|
17
|
-
await expect(page).toHaveURL(urlPattern);
|
|
18
|
-
}
|
|
19
|
-
export { expectNavigation };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
import { getRequestState } from '../core/requests.js';
|
|
17
|
-
async function expectRequest(page, { requestId, loading, response, payload, timeout = 30000 }) {
|
|
18
|
-
if (loading !== undefined) {
|
|
19
|
-
await expect.poll(async ()=>{
|
|
20
|
-
const state = await getRequestState(page, requestId);
|
|
21
|
-
return state?.loading;
|
|
22
|
-
}, {
|
|
23
|
-
timeout
|
|
24
|
-
}).toBe(loading);
|
|
25
|
-
}
|
|
26
|
-
if (response !== undefined) {
|
|
27
|
-
await expect.poll(async ()=>{
|
|
28
|
-
const state = await getRequestState(page, requestId);
|
|
29
|
-
return state?.response;
|
|
30
|
-
}, {
|
|
31
|
-
timeout
|
|
32
|
-
}).toEqual(expect.objectContaining(response));
|
|
33
|
-
}
|
|
34
|
-
// Payload is stored in the request state by the Lowdefy engine.
|
|
35
|
-
// It's the evaluated payload from the request config (client-side).
|
|
36
|
-
if (payload !== undefined) {
|
|
37
|
-
await expect.poll(async ()=>{
|
|
38
|
-
const state = await getRequestState(page, requestId);
|
|
39
|
-
return state?.payload;
|
|
40
|
-
}, {
|
|
41
|
-
timeout
|
|
42
|
-
}).toEqual(expect.objectContaining(payload));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export { expectRequest };
|
package/dist/assertions/state.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
import { get } from '@lowdefy/helpers';
|
|
17
|
-
import { getState } from '../core/state.js';
|
|
18
|
-
async function expectState(page, { key, value, timeout = 5000 }) {
|
|
19
|
-
await expect.poll(async ()=>{
|
|
20
|
-
const state = await getState(page);
|
|
21
|
-
return get(state, key);
|
|
22
|
-
}, {
|
|
23
|
-
timeout
|
|
24
|
-
}).toEqual(value);
|
|
25
|
-
}
|
|
26
|
-
export { expectState };
|
package/dist/assertions/url.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
async function expectUrl(page, { url, timeout = 5000 }) {
|
|
17
|
-
if (!url) {
|
|
18
|
-
throw new Error('expectUrl requires a "url" parameter (string or RegExp).');
|
|
19
|
-
}
|
|
20
|
-
await expect(page).toHaveURL(url, {
|
|
21
|
-
timeout
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
async function expectUrlQuery(page, { key, value, timeout = 5000 }) {
|
|
25
|
-
await expect.poll(async ()=>{
|
|
26
|
-
const url = new URL(page.url());
|
|
27
|
-
return url.searchParams.get(key);
|
|
28
|
-
}, {
|
|
29
|
-
timeout
|
|
30
|
-
}).toBe(value);
|
|
31
|
-
}
|
|
32
|
-
export { expectUrl, expectUrlQuery };
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { expect } from '@playwright/test';
|
|
16
|
-
import { getValidation } from '../core/validation.js';
|
|
17
|
-
async function expectValidationStatus(page, { blockId, status, timeout = 5000 }) {
|
|
18
|
-
await expect.poll(async ()=>{
|
|
19
|
-
const validation = await getValidation(page, blockId);
|
|
20
|
-
return validation?.status;
|
|
21
|
-
}, {
|
|
22
|
-
timeout
|
|
23
|
-
}).toBe(status);
|
|
24
|
-
}
|
|
25
|
-
async function expectValidationError(page, { blockId, message, timeout = 5000 }) {
|
|
26
|
-
await expect.poll(async ()=>{
|
|
27
|
-
const validation = await getValidation(page, blockId);
|
|
28
|
-
if (validation?.status !== 'error') return {
|
|
29
|
-
status: validation?.status
|
|
30
|
-
};
|
|
31
|
-
if (message && !validation?.errors?.includes(message)) {
|
|
32
|
-
return {
|
|
33
|
-
errors: validation?.errors
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
return true;
|
|
37
|
-
}, {
|
|
38
|
-
timeout
|
|
39
|
-
}).toBe(true);
|
|
40
|
-
}
|
|
41
|
-
async function expectValidationWarning(page, { blockId, message, timeout = 5000 }) {
|
|
42
|
-
await expect.poll(async ()=>{
|
|
43
|
-
const validation = await getValidation(page, blockId);
|
|
44
|
-
if (validation?.status !== 'warning') return {
|
|
45
|
-
status: validation?.status
|
|
46
|
-
};
|
|
47
|
-
if (message && !validation?.warnings?.includes(message)) {
|
|
48
|
-
return {
|
|
49
|
-
warnings: validation?.warnings
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return true;
|
|
53
|
-
}, {
|
|
54
|
-
timeout
|
|
55
|
-
}).toBe(true);
|
|
56
|
-
}
|
|
57
|
-
async function expectValidationSuccess(page, { blockId, timeout = 5000 }) {
|
|
58
|
-
await expectValidationStatus(page, {
|
|
59
|
-
blockId,
|
|
60
|
-
status: 'success',
|
|
61
|
-
timeout
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
export { expectValidationStatus, expectValidationError, expectValidationWarning, expectValidationSuccess };
|
package/dist/runtime.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ // Runner-agnostic surface: reading/writing a Lowdefy Page via the Playwright
|
|
16
|
-
// `page` interface, with no dependency on @playwright/test. Useful for driving
|
|
17
|
-
// a page from tooling that isn't a Playwright test run (e.g. headless
|
|
18
|
-
// inspection). The `expect*` assertion helpers live in "./assertions" and the
|
|
19
|
-
// full test-authoring API (which does depend on @playwright/test) is exported
|
|
20
|
-
// from "." and "./fixtures".
|
|
21
|
-
export { escapeId } from './core/escapeId.js';
|
|
22
|
-
export { getBlock } from './core/locators.js';
|
|
23
|
-
export { goto, waitForReady, waitForPage } from './core/navigation.js';
|
|
24
|
-
export { getRequestState, getRequestResponse } from './core/requests.js';
|
|
25
|
-
export { getApiState, getApiResponse } from './core/api.js';
|
|
26
|
-
export { getState, getBlockState, setState } from './core/state.js';
|
|
27
|
-
export { getValidation } from './core/validation.js';
|
|
28
|
-
export { setUrlQuery } from './core/url.js';
|
|
29
|
-
export { setUserCookie, clearUserCookie } from './core/userCookie.js';
|
|
30
|
-
export { generateManifest, loadManifest } from './testPrep/generateManifest.js';
|
|
31
|
-
export { createMockManager, loadStaticMocks } from './mocking/index.js';
|
|
32
|
-
export { default as createPageManager } from './proxy/createPageManager.js';
|