@simplysf/simply-utam-core 0.0.0
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/README.md +114 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +27 -0
- package/lib/index.js.map +1 -0
- package/lib/lightning-paths.d.ts +36 -0
- package/lib/lightning-paths.js +67 -0
- package/lib/lightning-paths.js.map +1 -0
- package/lib/navigator.d.ts +61 -0
- package/lib/navigator.js +87 -0
- package/lib/navigator.js.map +1 -0
- package/lib/test-environment.d.ts +43 -0
- package/lib/test-environment.js +68 -0
- package/lib/test-environment.js.map +1 -0
- package/lib/utam-html.d.ts +35 -0
- package/lib/utam-html.js +61 -0
- package/lib/utam-html.js.map +1 -0
- package/package.json +129 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# @simplysf/simply-utam-core
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/@simplysf/simply-utam-core) [](https://raw.githubusercontent.com/SimplySF/simply-utam/main/LICENSE.txt)
|
|
4
|
+
|
|
5
|
+
Org authentication, Lightning navigation, and debugging helpers for
|
|
6
|
+
[UTAM](https://utam.dev/) UI tests against Salesforce, built by [SimplySF](https://github.com/SimplySF).
|
|
7
|
+
|
|
8
|
+
It logs the test browser in to an org you have already authorized with the Salesforce CLI — no
|
|
9
|
+
passwords in the test project — and opens Lightning pages directly, so a test starts on the page it
|
|
10
|
+
is about instead of clicking its way there.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install --save-dev @simplysf/simply-utam-core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requires Node.js 22 or later, and an org authorized with `sf org login web` (or any other `sf org
|
|
19
|
+
login` flow) on the machine running the tests.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Point `UTAM_USERNAME` at the org's username or alias, then navigate from a WebdriverIO spec:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { LightningNavigator, logUtamHtml } from '@simplysf/simply-utam-core';
|
|
27
|
+
import AccountDetail from '../pageObjects/accountDetail'; // your compiled UTAM page object
|
|
28
|
+
|
|
29
|
+
const navigator = new LightningNavigator();
|
|
30
|
+
|
|
31
|
+
describe('Account record', () => {
|
|
32
|
+
it('opens on the detail page', async () => {
|
|
33
|
+
await navigator.goToRecord('MyApp', '001000000000001AAA');
|
|
34
|
+
|
|
35
|
+
const accountDetail = await utam.load(AccountDetail);
|
|
36
|
+
await logUtamHtml(accountDetail); // prints the selector and rendered HTML when a locator misbehaves
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`LightningNavigator` uses WebdriverIO's global `browser` by default and a `TestEnvironment` for
|
|
42
|
+
`UTAM_USERNAME`; pass either explicitly to override:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const navigator = new LightningNavigator({
|
|
46
|
+
environment: new TestEnvironment({ username: 'qa-sandbox' }),
|
|
47
|
+
browser,
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
App names are developer names. A bare name is treated as a custom app in the default namespace
|
|
52
|
+
(`MyApp` opens `c__MyApp`); a namespaced name such as `standard__Sales` is used as given.
|
|
53
|
+
|
|
54
|
+
### How login works
|
|
55
|
+
|
|
56
|
+
`TestEnvironment` loads the org from the Salesforce CLI's auth store with `@salesforce/core` and asks
|
|
57
|
+
Salesforce's [single-access endpoint](https://help.salesforce.com/s/articleView?id=xcloud.frontdoor_singleaccess.htm&type=5)
|
|
58
|
+
for a one-time frontdoor URL. The access token never appears in a URL, so it does not end up in
|
|
59
|
+
browser history, WebDriver logs, or a screenshot of the address bar. The org is authenticated once per
|
|
60
|
+
`TestEnvironment` and shared by every navigation.
|
|
61
|
+
|
|
62
|
+
## API
|
|
63
|
+
|
|
64
|
+
Everything below is exported from the package root and is semver-covered. Anything not listed is
|
|
65
|
+
internal.
|
|
66
|
+
|
|
67
|
+
### Org authentication
|
|
68
|
+
|
|
69
|
+
| Export | Description |
|
|
70
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `TestEnvironment` | The org under test. `new TestEnvironment({ username?, env? })` throws when neither a username nor `UTAM_USERNAME` is set. |
|
|
72
|
+
| `testEnvironment.getOrg()` | The authenticated `Org`. Authenticates on first call and shares the result; a failure is not cached. |
|
|
73
|
+
| `testEnvironment.init()` | Authenticates eagerly, for a runner hook that wants auth failures reported before any test starts. Optional. |
|
|
74
|
+
| `testEnvironment.buildFrontdoorUrl(returnUrl?)` | A one-time URL that logs a browser in and lands on `returnUrl`. |
|
|
75
|
+
| `USERNAME_ENV` | `'UTAM_USERNAME'`. |
|
|
76
|
+
| `TestEnvironmentOptions`, `EnvLike` | Types for the constructor options and an environment-shaped map. |
|
|
77
|
+
|
|
78
|
+
### Navigation
|
|
79
|
+
|
|
80
|
+
| Export | Description |
|
|
81
|
+
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
82
|
+
| `LightningNavigator` | `new LightningNavigator({ environment?, browser? })`; every method logs in and opens a page. |
|
|
83
|
+
| `navigator.goToLoginUrl(returnUrl?)` | Log in and open any path, or the org's default landing page. |
|
|
84
|
+
| `navigator.goToApplication(app)` | An app's home page. |
|
|
85
|
+
| `navigator.goToCreateNewRecord(app, objectApiName)` | An object's new-record form. |
|
|
86
|
+
| `navigator.goToRecord(app, recordId)` | A record's detail page. |
|
|
87
|
+
| `navigator.goToRelatedList(app, recordId, relatedListName)` | One of a record's related lists. |
|
|
88
|
+
| `applicationPath`, `newRecordPath`, `recordPath`, `relatedListPath` | The Lightning paths the methods above open, for a caller building its own URLs. |
|
|
89
|
+
| `lightningAppName(app)` | The namespacing rule: `MyApp` becomes `c__MyApp`, a namespaced name is unchanged. |
|
|
90
|
+
| `NavigableBrowser`, `FrontdoorUrlSource`, `LightningNavigatorOptions` | Structural types: anything with `navigateTo(url)`, anything with `buildFrontdoorUrl(returnUrl?)`. |
|
|
91
|
+
|
|
92
|
+
### Debugging
|
|
93
|
+
|
|
94
|
+
| Export | Description |
|
|
95
|
+
| ------------------------------- | ------------------------------------------------------------------------------------- |
|
|
96
|
+
| `logUtamHtml(utamObject, log?)` | Logs the selector a UTAM object resolved through and its HTML, shadow roots included. |
|
|
97
|
+
| `getUtamHtml(utamObject)` | The same `{ selector, html }` without logging it, e.g. to attach to a test report. |
|
|
98
|
+
| `formatUtamHtml(utamHtml)` | The colored block `logUtamHtml` writes. |
|
|
99
|
+
| `UtamElementLike`, `UtamHtml` | Types: any UTAM page object or element, and what it resolved to. |
|
|
100
|
+
|
|
101
|
+
WebdriverIO and UTAM are not dependencies: the browser and UTAM objects are typed structurally, so
|
|
102
|
+
the package works with whichever versions your test project already uses.
|
|
103
|
+
|
|
104
|
+
## Issues
|
|
105
|
+
|
|
106
|
+
Please report any issues at https://github.com/SimplySF/simply-utam/issues
|
|
107
|
+
|
|
108
|
+
## Contributing
|
|
109
|
+
|
|
110
|
+
This package is part of the [`simply-utam`](https://github.com/SimplySF/simply-utam) monorepo. See [CONTRIBUTING.md](CONTRIBUTING.md) for what's specific to this package, and the repo's [root CONTRIBUTING.md](https://github.com/SimplySF/simply-utam/blob/main/CONTRIBUTING.md) for repo structure, setup, commit conventions, and how to submit a pull request. Please also read our [Code of Conduct](https://github.com/SimplySF/simply-utam/blob/main/CODE_OF_CONDUCT.md).
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
Licensed under the [Apache-2.0](https://raw.githubusercontent.com/SimplySF/simply-utam/main/LICENSE.txt) license.
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TestEnvironment, USERNAME_ENV, type EnvLike, type TestEnvironmentOptions } from './test-environment.js';
|
|
2
|
+
export { applicationPath, lightningAppName, newRecordPath, recordPath, relatedListPath } from './lightning-paths.js';
|
|
3
|
+
export { LightningNavigator, type FrontdoorUrlSource, type LightningNavigatorOptions, type NavigableBrowser, } from './navigator.js';
|
|
4
|
+
export { formatUtamHtml, getUtamHtml, logUtamHtml, type UtamElementLike, type UtamHtml } from './utam-html.js';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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
|
+
*/
|
|
16
|
+
// Everything exported from this file is this package's public API and is semver-covered: adding
|
|
17
|
+
// an export is a minor/patch change, but removing or renaming one is breaking.
|
|
18
|
+
// `test/index.test.ts` pins the exported-key list so an accidental removal fails a test instead
|
|
19
|
+
// of silently shipping in a patch release.
|
|
20
|
+
//
|
|
21
|
+
// Nothing here depends on WebdriverIO or UTAM at runtime: the browser and UTAM objects are typed
|
|
22
|
+
// structurally, so consumers bring whichever versions their test project already uses.
|
|
23
|
+
export { TestEnvironment, USERNAME_ENV } from './test-environment.js';
|
|
24
|
+
export { applicationPath, lightningAppName, newRecordPath, recordPath, relatedListPath } from './lightning-paths.js';
|
|
25
|
+
export { LightningNavigator, } from './navigator.js';
|
|
26
|
+
export { formatUtamHtml, getUtamHtml, logUtamHtml } from './utam-html.js';
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,gGAAgG;AAChG,+EAA+E;AAC/E,gGAAgG;AAChG,2CAA2C;AAC3C,EAAE;AACF,iGAAiG;AACjG,uFAAuF;AAEvF,OAAO,EAAE,eAAe,EAAE,YAAY,EAA6C,MAAM,uBAAuB,CAAC;AACjH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACrH,OAAO,EACL,kBAAkB,GAInB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAuC,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The app segment of a Lightning URL. A bare developer name is a custom app in the default
|
|
3
|
+
* namespace (`MyApp` becomes `c__MyApp`); a name that already carries a namespace
|
|
4
|
+
* (`standard__Sales`, `acme__Billing`) is used as given.
|
|
5
|
+
*
|
|
6
|
+
* @param applicationName The app's developer name, with or without a namespace prefix.
|
|
7
|
+
*/
|
|
8
|
+
export declare function lightningAppName(applicationName: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* The home page of a Lightning app.
|
|
11
|
+
*
|
|
12
|
+
* @param applicationName The app's developer name.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applicationPath(applicationName: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* The new-record form for an object, opened inside a Lightning app.
|
|
17
|
+
*
|
|
18
|
+
* @param applicationName The app's developer name.
|
|
19
|
+
* @param objectApiName The object's API name, e.g. `Account` or `Invoice__c`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function newRecordPath(applicationName: string, objectApiName: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* A record's detail page, opened inside a Lightning app.
|
|
24
|
+
*
|
|
25
|
+
* @param applicationName The app's developer name.
|
|
26
|
+
* @param recordId The record's 15- or 18-character id.
|
|
27
|
+
*/
|
|
28
|
+
export declare function recordPath(applicationName: string, recordId: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* One of a record's related lists, opened inside a Lightning app.
|
|
31
|
+
*
|
|
32
|
+
* @param applicationName The app's developer name.
|
|
33
|
+
* @param recordId The parent record's id.
|
|
34
|
+
* @param relatedListName The relationship name, e.g. `Contacts` or `Invoice_Lines__r`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function relatedListPath(applicationName: string, recordId: string, relatedListName: string): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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
|
+
*/
|
|
16
|
+
// Lightning Experience paths, relative to the org's instance URL. Each is what a frontdoor URL's
|
|
17
|
+
// return path points at; `LightningNavigator` pairs them with a login.
|
|
18
|
+
/**
|
|
19
|
+
* The app segment of a Lightning URL. A bare developer name is a custom app in the default
|
|
20
|
+
* namespace (`MyApp` becomes `c__MyApp`); a name that already carries a namespace
|
|
21
|
+
* (`standard__Sales`, `acme__Billing`) is used as given.
|
|
22
|
+
*
|
|
23
|
+
* @param applicationName The app's developer name, with or without a namespace prefix.
|
|
24
|
+
*/
|
|
25
|
+
export function lightningAppName(applicationName) {
|
|
26
|
+
return applicationName.includes('__') ? applicationName : `c__${applicationName}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The home page of a Lightning app.
|
|
30
|
+
*
|
|
31
|
+
* @param applicationName The app's developer name.
|
|
32
|
+
*/
|
|
33
|
+
export function applicationPath(applicationName) {
|
|
34
|
+
return `${appBase(applicationName)}/page/home`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The new-record form for an object, opened inside a Lightning app.
|
|
38
|
+
*
|
|
39
|
+
* @param applicationName The app's developer name.
|
|
40
|
+
* @param objectApiName The object's API name, e.g. `Account` or `Invoice__c`.
|
|
41
|
+
*/
|
|
42
|
+
export function newRecordPath(applicationName, objectApiName) {
|
|
43
|
+
return `${appBase(applicationName)}/o/${encodeURIComponent(objectApiName)}/new`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A record's detail page, opened inside a Lightning app.
|
|
47
|
+
*
|
|
48
|
+
* @param applicationName The app's developer name.
|
|
49
|
+
* @param recordId The record's 15- or 18-character id.
|
|
50
|
+
*/
|
|
51
|
+
export function recordPath(applicationName, recordId) {
|
|
52
|
+
return `${appBase(applicationName)}/r/${encodeURIComponent(recordId)}/view`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One of a record's related lists, opened inside a Lightning app.
|
|
56
|
+
*
|
|
57
|
+
* @param applicationName The app's developer name.
|
|
58
|
+
* @param recordId The parent record's id.
|
|
59
|
+
* @param relatedListName The relationship name, e.g. `Contacts` or `Invoice_Lines__r`.
|
|
60
|
+
*/
|
|
61
|
+
export function relatedListPath(applicationName, recordId, relatedListName) {
|
|
62
|
+
return `${appBase(applicationName)}/r/${encodeURIComponent(recordId)}/related/${encodeURIComponent(relatedListName)}/view`;
|
|
63
|
+
}
|
|
64
|
+
function appBase(applicationName) {
|
|
65
|
+
return `/lightning/app/${encodeURIComponent(lightningAppName(applicationName))}`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=lightning-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lightning-paths.js","sourceRoot":"","sources":["../src/lightning-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,iGAAiG;AACjG,uEAAuE;AAEvE;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,eAAuB;IACtD,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,eAAuB;IACrD,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,eAAuB,EAAE,aAAqB;IAC1E,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,kBAAkB,CAAC,aAAa,CAAC,MAAM,CAAC;AAClF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,eAAuB,EAAE,QAAgB;IAClE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,eAAuB,EAAE,QAAgB,EAAE,eAAuB;IAChG,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,kBAAkB,CAAC,QAAQ,CAAC,YAAY,kBAAkB,CAAC,eAAe,CAAC,OAAO,CAAC;AAC7H,CAAC;AAED,SAAS,OAAO,CAAC,eAAuB;IACtC,OAAO,kBAAkB,kBAAkB,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** The part of a WebdriverIO browser the navigator drives. */
|
|
2
|
+
export type NavigableBrowser = {
|
|
3
|
+
navigateTo(url: string): Promise<unknown>;
|
|
4
|
+
};
|
|
5
|
+
/** Anything that can mint a logged-in URL; `TestEnvironment` in practice. */
|
|
6
|
+
export type FrontdoorUrlSource = {
|
|
7
|
+
buildFrontdoorUrl(returnUrl?: string): Promise<string>;
|
|
8
|
+
};
|
|
9
|
+
export type LightningNavigatorOptions = {
|
|
10
|
+
/** Where login URLs come from. Defaults to a `TestEnvironment` for `UTAM_USERNAME`. */
|
|
11
|
+
environment?: FrontdoorUrlSource;
|
|
12
|
+
/** The browser to drive. Defaults to WebdriverIO's global `browser`, looked up on each call. */
|
|
13
|
+
browser?: NavigableBrowser;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Logs the browser in to the test org and opens a Lightning page in one step. Every navigation
|
|
17
|
+
* goes through a fresh frontdoor URL, so each one also works as the first thing a test does.
|
|
18
|
+
*/
|
|
19
|
+
export declare class LightningNavigator {
|
|
20
|
+
#private;
|
|
21
|
+
/**
|
|
22
|
+
* Create a navigator.
|
|
23
|
+
*
|
|
24
|
+
* @param options The environment and browser to use; both have defaults.
|
|
25
|
+
*/
|
|
26
|
+
constructor(options?: LightningNavigatorOptions);
|
|
27
|
+
/**
|
|
28
|
+
* Log in and open `returnUrl`, or the org's default landing page when it is omitted.
|
|
29
|
+
*
|
|
30
|
+
* @param returnUrl Path to open after login.
|
|
31
|
+
*/
|
|
32
|
+
goToLoginUrl(returnUrl?: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Log in and open a Lightning app's home page.
|
|
35
|
+
*
|
|
36
|
+
* @param applicationName The app's developer name; see `lightningAppName` for namespacing.
|
|
37
|
+
*/
|
|
38
|
+
goToApplication(applicationName: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Log in and open the new-record form for an object.
|
|
41
|
+
*
|
|
42
|
+
* @param applicationName The app's developer name.
|
|
43
|
+
* @param objectApiName The object's API name.
|
|
44
|
+
*/
|
|
45
|
+
goToCreateNewRecord(applicationName: string, objectApiName: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Log in and open a record's detail page.
|
|
48
|
+
*
|
|
49
|
+
* @param applicationName The app's developer name.
|
|
50
|
+
* @param recordId The record's id.
|
|
51
|
+
*/
|
|
52
|
+
goToRecord(applicationName: string, recordId: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Log in and open one of a record's related lists.
|
|
55
|
+
*
|
|
56
|
+
* @param applicationName The app's developer name.
|
|
57
|
+
* @param recordId The parent record's id.
|
|
58
|
+
* @param relatedListName The relationship name.
|
|
59
|
+
*/
|
|
60
|
+
goToRelatedList(applicationName: string, recordId: string, relatedListName: string): Promise<void>;
|
|
61
|
+
}
|
package/lib/navigator.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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
|
+
*/
|
|
16
|
+
import { applicationPath, newRecordPath, recordPath, relatedListPath } from './lightning-paths.js';
|
|
17
|
+
import { TestEnvironment } from './test-environment.js';
|
|
18
|
+
/**
|
|
19
|
+
* Logs the browser in to the test org and opens a Lightning page in one step. Every navigation
|
|
20
|
+
* goes through a fresh frontdoor URL, so each one also works as the first thing a test does.
|
|
21
|
+
*/
|
|
22
|
+
export class LightningNavigator {
|
|
23
|
+
#environment;
|
|
24
|
+
#browser;
|
|
25
|
+
/**
|
|
26
|
+
* Create a navigator.
|
|
27
|
+
*
|
|
28
|
+
* @param options The environment and browser to use; both have defaults.
|
|
29
|
+
*/
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.#environment = options.environment ?? new TestEnvironment();
|
|
32
|
+
this.#browser = options.browser;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Log in and open `returnUrl`, or the org's default landing page when it is omitted.
|
|
36
|
+
*
|
|
37
|
+
* @param returnUrl Path to open after login.
|
|
38
|
+
*/
|
|
39
|
+
async goToLoginUrl(returnUrl) {
|
|
40
|
+
const url = await this.#environment.buildFrontdoorUrl(returnUrl);
|
|
41
|
+
await this.#resolveBrowser().navigateTo(url);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Log in and open a Lightning app's home page.
|
|
45
|
+
*
|
|
46
|
+
* @param applicationName The app's developer name; see `lightningAppName` for namespacing.
|
|
47
|
+
*/
|
|
48
|
+
async goToApplication(applicationName) {
|
|
49
|
+
await this.goToLoginUrl(applicationPath(applicationName));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Log in and open the new-record form for an object.
|
|
53
|
+
*
|
|
54
|
+
* @param applicationName The app's developer name.
|
|
55
|
+
* @param objectApiName The object's API name.
|
|
56
|
+
*/
|
|
57
|
+
async goToCreateNewRecord(applicationName, objectApiName) {
|
|
58
|
+
await this.goToLoginUrl(newRecordPath(applicationName, objectApiName));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Log in and open a record's detail page.
|
|
62
|
+
*
|
|
63
|
+
* @param applicationName The app's developer name.
|
|
64
|
+
* @param recordId The record's id.
|
|
65
|
+
*/
|
|
66
|
+
async goToRecord(applicationName, recordId) {
|
|
67
|
+
await this.goToLoginUrl(recordPath(applicationName, recordId));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Log in and open one of a record's related lists.
|
|
71
|
+
*
|
|
72
|
+
* @param applicationName The app's developer name.
|
|
73
|
+
* @param recordId The parent record's id.
|
|
74
|
+
* @param relatedListName The relationship name.
|
|
75
|
+
*/
|
|
76
|
+
async goToRelatedList(applicationName, recordId, relatedListName) {
|
|
77
|
+
await this.goToLoginUrl(relatedListPath(applicationName, recordId, relatedListName));
|
|
78
|
+
}
|
|
79
|
+
#resolveBrowser() {
|
|
80
|
+
const browser = this.#browser ?? globalThis.browser;
|
|
81
|
+
if (!browser) {
|
|
82
|
+
throw new Error('No browser to navigate: pass one as the `browser` option, or run inside WebdriverIO so the global `browser` exists');
|
|
83
|
+
}
|
|
84
|
+
return browser;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=navigator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigator.js","sourceRoot":"","sources":["../src/navigator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAmBxD;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACpB,YAAY,CAAqB;IACjC,QAAQ,CAAoB;IAErC;;;;OAIG;IACH,YAAmB,UAAqC,EAAE;QACxD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,eAAe,EAAE,CAAC;QACjE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,YAAY,CAAC,SAAkB;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe,CAAC,eAAuB;QAClD,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,mBAAmB,CAAC,eAAuB,EAAE,aAAqB;QAC7E,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;IACzE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,UAAU,CAAC,eAAuB,EAAE,QAAgB;QAC/D,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjE,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,eAAe,CAAC,eAAuB,EAAE,QAAgB,EAAE,eAAuB;QAC7F,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,eAAe,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IACvF,CAAC;IAED,eAAe;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAK,UAA6C,CAAC,OAAO,CAAC;QACxF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,oHAAoH,CACrH,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Org } from '@salesforce/core';
|
|
2
|
+
/** The environment variable naming the org a UTAM run authenticates to. */
|
|
3
|
+
export declare const USERNAME_ENV = "UTAM_USERNAME";
|
|
4
|
+
/** An environment-shaped map; `process.env` by default. */
|
|
5
|
+
export type EnvLike = Record<string, string | undefined>;
|
|
6
|
+
export type TestEnvironmentOptions = {
|
|
7
|
+
/** Username or alias of an org already authorized with the Salesforce CLI. Wins over `UTAM_USERNAME`. */
|
|
8
|
+
username?: string;
|
|
9
|
+
/** Where `UTAM_USERNAME` is read from. Defaults to `process.env`. */
|
|
10
|
+
env?: EnvLike;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The org a UTAM run tests against, resolved from the Salesforce CLI's local auth store.
|
|
14
|
+
*/
|
|
15
|
+
export declare class TestEnvironment {
|
|
16
|
+
#private;
|
|
17
|
+
readonly username: string;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new environment for the given username, or `UTAM_USERNAME` when none is passed.
|
|
20
|
+
*
|
|
21
|
+
* @param options Explicit username and environment overrides.
|
|
22
|
+
*/
|
|
23
|
+
constructor(options?: TestEnvironmentOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the authenticated org. The first call authenticates and every later call shares its
|
|
26
|
+
* result, so callers need not coordinate who goes first; a failed attempt is not cached.
|
|
27
|
+
*/
|
|
28
|
+
getOrg(): Promise<Org>;
|
|
29
|
+
/**
|
|
30
|
+
* Authenticate eagerly, for a runner hook that wants auth failures reported before any test
|
|
31
|
+
* starts. Optional: every other method authenticates on first use.
|
|
32
|
+
*/
|
|
33
|
+
init(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Build a single-use frontdoor URL that logs the browser in and lands on `returnUrl`.
|
|
36
|
+
*
|
|
37
|
+
* The URL comes from Salesforce's single-access endpoint rather than a `sid=` query parameter,
|
|
38
|
+
* so the session's access token never appears in the browser's address bar or history.
|
|
39
|
+
*
|
|
40
|
+
* @param returnUrl Path to open after login, e.g. `/lightning/page/home`. Omit for the org's default landing page.
|
|
41
|
+
*/
|
|
42
|
+
buildFrontdoorUrl(returnUrl?: string): Promise<string>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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
|
+
*/
|
|
16
|
+
import { Org } from '@salesforce/core';
|
|
17
|
+
/** The environment variable naming the org a UTAM run authenticates to. */
|
|
18
|
+
export const USERNAME_ENV = 'UTAM_USERNAME';
|
|
19
|
+
/**
|
|
20
|
+
* The org a UTAM run tests against, resolved from the Salesforce CLI's local auth store.
|
|
21
|
+
*/
|
|
22
|
+
export class TestEnvironment {
|
|
23
|
+
username;
|
|
24
|
+
#org;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new environment for the given username, or `UTAM_USERNAME` when none is passed.
|
|
27
|
+
*
|
|
28
|
+
* @param options Explicit username and environment overrides.
|
|
29
|
+
*/
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
const username = options.username ?? (options.env ?? process.env)[USERNAME_ENV];
|
|
32
|
+
if (!username) {
|
|
33
|
+
throw new Error(`You must set a username using the ${USERNAME_ENV} env property for the test`);
|
|
34
|
+
}
|
|
35
|
+
this.username = username;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the authenticated org. The first call authenticates and every later call shares its
|
|
39
|
+
* result, so callers need not coordinate who goes first; a failed attempt is not cached.
|
|
40
|
+
*/
|
|
41
|
+
async getOrg() {
|
|
42
|
+
this.#org ??= Org.create({ aliasOrUsername: this.username }).catch((error) => {
|
|
43
|
+
this.#org = undefined;
|
|
44
|
+
throw error;
|
|
45
|
+
});
|
|
46
|
+
return this.#org;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Authenticate eagerly, for a runner hook that wants auth failures reported before any test
|
|
50
|
+
* starts. Optional: every other method authenticates on first use.
|
|
51
|
+
*/
|
|
52
|
+
async init() {
|
|
53
|
+
await this.getOrg();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build a single-use frontdoor URL that logs the browser in and lands on `returnUrl`.
|
|
57
|
+
*
|
|
58
|
+
* The URL comes from Salesforce's single-access endpoint rather than a `sid=` query parameter,
|
|
59
|
+
* so the session's access token never appears in the browser's address bar or history.
|
|
60
|
+
*
|
|
61
|
+
* @param returnUrl Path to open after login, e.g. `/lightning/page/home`. Omit for the org's default landing page.
|
|
62
|
+
*/
|
|
63
|
+
async buildFrontdoorUrl(returnUrl) {
|
|
64
|
+
const org = await this.getOrg();
|
|
65
|
+
return org.getFrontDoorUrl(returnUrl);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=test-environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-environment.js","sourceRoot":"","sources":["../src/test-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAY5C;;GAEG;AACH,MAAM,OAAO,eAAe;IACV,QAAQ,CAAS;IAEjC,IAAI,CAAgB;IAEpB;;;;OAIG;IACH,YAAmB,UAAkC,EAAE;QACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;QAChF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,YAAY,4BAA4B,CAAC,CAAC;QACjG,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,MAAM;QACjB,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACpF,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;YACtB,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,IAAI;QACf,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;IACtB,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,iBAAiB,CAAC,SAAkB;QAC/C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,OAAO,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** The part of a UTAM page object or element this module reads: its wrapped WebdriverIO element. */
|
|
2
|
+
export type UtamElementLike = {
|
|
3
|
+
element: {
|
|
4
|
+
element: {
|
|
5
|
+
selector: unknown;
|
|
6
|
+
getHTML(options?: {
|
|
7
|
+
serializableShadowRoots?: boolean;
|
|
8
|
+
}): Promise<string>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
/** What a UTAM object resolved to in the page. */
|
|
13
|
+
export type UtamHtml = {
|
|
14
|
+
selector: string;
|
|
15
|
+
html: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Read the selector a UTAM object resolved through and its rendered HTML, shadow roots included.
|
|
19
|
+
*
|
|
20
|
+
* @param utamObject A UTAM page object or element.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getUtamHtml(utamObject: UtamElementLike): Promise<UtamHtml>;
|
|
23
|
+
/**
|
|
24
|
+
* Render a `getUtamHtml` result as a colored block for a terminal.
|
|
25
|
+
*
|
|
26
|
+
* @param utamHtml The selector and HTML to render.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatUtamHtml(utamHtml: UtamHtml): string;
|
|
29
|
+
/**
|
|
30
|
+
* Log what a UTAM object resolved to, for working out why a locator does not match.
|
|
31
|
+
*
|
|
32
|
+
* @param utamObject A UTAM page object or element.
|
|
33
|
+
* @param log Where the block is written. Defaults to `console.log`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function logUtamHtml(utamObject: UtamElementLike, log?: (message: string) => void): Promise<void>;
|
package/lib/utam-html.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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
|
+
*/
|
|
16
|
+
const colors = {
|
|
17
|
+
reset: '\x1b[0m',
|
|
18
|
+
brightCyanBackground: '\x1b[106m',
|
|
19
|
+
cyan: '\x1b[36m',
|
|
20
|
+
green: '\x1b[32m',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Read the selector a UTAM object resolved through and its rendered HTML, shadow roots included.
|
|
24
|
+
*
|
|
25
|
+
* @param utamObject A UTAM page object or element.
|
|
26
|
+
*/
|
|
27
|
+
export async function getUtamHtml(utamObject) {
|
|
28
|
+
const element = utamObject.element.element;
|
|
29
|
+
return {
|
|
30
|
+
selector: describeSelector(element.selector),
|
|
31
|
+
html: await element.getHTML({ serializableShadowRoots: true }),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Render a `getUtamHtml` result as a colored block for a terminal.
|
|
36
|
+
*
|
|
37
|
+
* @param utamHtml The selector and HTML to render.
|
|
38
|
+
*/
|
|
39
|
+
export function formatUtamHtml(utamHtml) {
|
|
40
|
+
return (`${colors.brightCyanBackground}Logging UTAM Html${colors.reset} ${colors.cyan}selector${colors.reset} ` +
|
|
41
|
+
`${utamHtml.selector}\n${colors.green}${utamHtml.html}${colors.reset}`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Log what a UTAM object resolved to, for working out why a locator does not match.
|
|
45
|
+
*
|
|
46
|
+
* @param utamObject A UTAM page object or element.
|
|
47
|
+
* @param log Where the block is written. Defaults to `console.log`.
|
|
48
|
+
*/
|
|
49
|
+
export async function logUtamHtml(utamObject,
|
|
50
|
+
// eslint-disable-next-line no-console -- logging is this function's purpose; `log` lets a caller redirect it
|
|
51
|
+
log = (message) => console.log(message)) {
|
|
52
|
+
log(formatUtamHtml(await getUtamHtml(utamObject)));
|
|
53
|
+
}
|
|
54
|
+
function describeSelector(selector) {
|
|
55
|
+
if (typeof selector === 'string')
|
|
56
|
+
return selector;
|
|
57
|
+
if (typeof selector === 'function')
|
|
58
|
+
return selector.name || 'anonymous function';
|
|
59
|
+
return JSON.stringify(selector) ?? String(selector);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=utam-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utam-html.js","sourceRoot":"","sources":["../src/utam-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAkBH,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,SAAS;IAChB,oBAAoB,EAAE,WAAW;IACjC,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAA2B;IAC3D,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC;IAC3C,OAAO;QACL,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC5C,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAkB;IAC/C,OAAO,CACL,GAAG,MAAM,CAAC,oBAAoB,oBAAoB,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,WAAW,MAAM,CAAC,KAAK,GAAG;QACvG,GAAG,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CACvE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAA2B;AAC3B,6GAA6G;AAC7G,MAAiC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IAElE,GAAG,CAAC,cAAc,CAAC,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAiB;IACzC,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAClD,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC,IAAI,IAAI,oBAAoB,CAAC;IACjF,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;AACtD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@simplysf/simply-utam-core",
|
|
3
|
+
"description": "Org authentication, Lightning navigation, and debugging helpers for UTAM UI tests against Salesforce",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"author": "@ClayChipps",
|
|
6
|
+
"homepage": "https://github.com/SimplySF/simply-utam",
|
|
7
|
+
"bugs": "https://github.com/SimplySF/simply-utam/issues",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/SimplySF/simply-utam",
|
|
11
|
+
"directory": "packages/simply-utam-core"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=22.0.0"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"/lib"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"utam",
|
|
21
|
+
"salesforce",
|
|
22
|
+
"webdriverio",
|
|
23
|
+
"ui-testing",
|
|
24
|
+
"simply"
|
|
25
|
+
],
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./lib/index.js",
|
|
29
|
+
"types": "./lib/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./lib/index.d.ts",
|
|
33
|
+
"default": "./lib/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@salesforce/core": "^9.1.7"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
41
|
+
"vitest": "^4.1.10"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "wireit",
|
|
48
|
+
"compile": "wireit",
|
|
49
|
+
"fix-license": "eslint src test --fix --rule \"header/header: [2]\"",
|
|
50
|
+
"format": "wireit",
|
|
51
|
+
"lint": "wireit",
|
|
52
|
+
"test": "wireit",
|
|
53
|
+
"test:coverage": "vitest run --coverage --project simply-utam-core",
|
|
54
|
+
"test:only": "wireit",
|
|
55
|
+
"test:watch": "vitest watch --project simply-utam-core"
|
|
56
|
+
},
|
|
57
|
+
"wireit": {
|
|
58
|
+
"build": {
|
|
59
|
+
"dependencies": [
|
|
60
|
+
"compile",
|
|
61
|
+
"lint"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"compile": {
|
|
65
|
+
"command": "tsc -p . --pretty --incremental",
|
|
66
|
+
"files": [
|
|
67
|
+
"src/**/*.ts",
|
|
68
|
+
"**/tsconfig.json",
|
|
69
|
+
"../../tsconfig.json"
|
|
70
|
+
],
|
|
71
|
+
"output": [
|
|
72
|
+
"lib/**",
|
|
73
|
+
"*.tsbuildinfo"
|
|
74
|
+
],
|
|
75
|
+
"clean": "if-file-deleted"
|
|
76
|
+
},
|
|
77
|
+
"format": {
|
|
78
|
+
"command": "prettier --write \"+(src|test)/**/*.+(ts|js|json)\"",
|
|
79
|
+
"files": [
|
|
80
|
+
"src/**/*.ts",
|
|
81
|
+
"test/**/*.ts",
|
|
82
|
+
".prettier*"
|
|
83
|
+
],
|
|
84
|
+
"output": []
|
|
85
|
+
},
|
|
86
|
+
"lint": {
|
|
87
|
+
"command": "eslint src test --color --cache --cache-location .eslintcache",
|
|
88
|
+
"files": [
|
|
89
|
+
"src/**/*.ts",
|
|
90
|
+
"test/**/*.ts",
|
|
91
|
+
"**/.eslint*",
|
|
92
|
+
"**/tsconfig.json",
|
|
93
|
+
"../../eslint.config.mjs",
|
|
94
|
+
"../../tsconfig.json"
|
|
95
|
+
],
|
|
96
|
+
"output": []
|
|
97
|
+
},
|
|
98
|
+
"test": {
|
|
99
|
+
"dependencies": [
|
|
100
|
+
"test:compile",
|
|
101
|
+
"test:only",
|
|
102
|
+
"lint"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"test:compile": {
|
|
106
|
+
"command": "tsc -p \"./test\" --pretty",
|
|
107
|
+
"files": [
|
|
108
|
+
"test/**/*.ts",
|
|
109
|
+
"**/tsconfig.json",
|
|
110
|
+
"../../tsconfig.json"
|
|
111
|
+
],
|
|
112
|
+
"output": []
|
|
113
|
+
},
|
|
114
|
+
"test:only": {
|
|
115
|
+
"command": "vitest run --project simply-utam-core",
|
|
116
|
+
"env": {
|
|
117
|
+
"FORCE_COLOR": "2"
|
|
118
|
+
},
|
|
119
|
+
"files": [
|
|
120
|
+
"test/**/*.ts",
|
|
121
|
+
"src/**/*.ts",
|
|
122
|
+
"**/tsconfig.json",
|
|
123
|
+
"../../tsconfig.json",
|
|
124
|
+
"../../vitest.config.ts"
|
|
125
|
+
],
|
|
126
|
+
"output": []
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|