@agent-smith/feat-frontend 0.0.1 → 0.0.2

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.
Files changed (30) hide show
  1. package/dist/actions/playwright-cli-playbook.js +74 -0
  2. package/dist/actions/playwright-cli.js +8 -6
  3. package/dist/agents/browser-agent.yml +3 -10
  4. package/dist/agents/frontend-assistant.yml +3 -3
  5. package/dist/agents/frontend-light.yml +0 -2
  6. package/dist/agents/frontend-team.yml +5 -4
  7. package/dist/agents/frontend.yml +0 -2
  8. package/dist/fragments/agents-manager-ts.md +1 -3
  9. package/dist/skills/playwright-cli/SKILL.md +5 -196
  10. package/dist/skills/playwright-cli-full/SKILL.md +403 -0
  11. package/dist/skills/playwright-cli-full/references/element-attributes.md +23 -0
  12. package/dist/skills/playwright-cli-full/references/playwright-tests.md +39 -0
  13. package/dist/skills/playwright-cli-full/references/request-mocking.md +87 -0
  14. package/dist/skills/playwright-cli-full/references/running-code.md +241 -0
  15. package/dist/skills/playwright-cli-full/references/session-management.md +225 -0
  16. package/dist/skills/playwright-cli-full/references/storage-state.md +275 -0
  17. package/dist/skills/playwright-cli-full/references/test-generation.md +433 -0
  18. package/dist/skills/playwright-cli-full/references/tracing.md +139 -0
  19. package/dist/skills/playwright-cli-full/references/video-recording.md +143 -0
  20. package/dist/skills/playwright-cli-mini/SKILL.md +164 -0
  21. package/dist/skills/playwright-cli-mini/references/element-attributes.md +23 -0
  22. package/dist/skills/playwright-cli-mini/references/playwright-tests.md +39 -0
  23. package/dist/skills/playwright-cli-mini/references/request-mocking.md +87 -0
  24. package/dist/skills/playwright-cli-mini/references/running-code.md +241 -0
  25. package/dist/skills/playwright-cli-mini/references/session-management.md +225 -0
  26. package/dist/skills/playwright-cli-mini/references/storage-state.md +275 -0
  27. package/dist/skills/playwright-cli-mini/references/test-generation.md +433 -0
  28. package/dist/skills/playwright-cli-mini/references/tracing.md +139 -0
  29. package/dist/skills/playwright-cli-mini/references/video-recording.md +143 -0
  30. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ # Tracing
2
+
3
+ Capture detailed execution traces for debugging and analysis. Traces include DOM snapshots, screenshots, network activity, and console logs.
4
+
5
+ ## Basic Usage
6
+
7
+ ```bash
8
+ # Start trace recording
9
+ playwright-cli tracing-start
10
+
11
+ # Perform actions
12
+ playwright-cli open https://example.com
13
+ playwright-cli click e1
14
+ playwright-cli fill e2 "test"
15
+
16
+ # Stop trace recording
17
+ playwright-cli tracing-stop
18
+ ```
19
+
20
+ ## Trace Output Files
21
+
22
+ When you start tracing, Playwright creates a `.playwright-cli/traces/` directory with several files:
23
+
24
+ ### `trace-{timestamp}.trace`
25
+
26
+ **Action log** - The main trace file containing:
27
+ - Every action performed (clicks, fills, navigations)
28
+ - DOM snapshots before and after each action
29
+ - Screenshots at each step
30
+ - Timing information
31
+ - Console messages
32
+ - Source locations
33
+
34
+ ### `trace-{timestamp}.network`
35
+
36
+ **Network log** - Complete network activity:
37
+ - All HTTP requests and responses
38
+ - Request headers and bodies
39
+ - Response headers and bodies
40
+ - Timing (DNS, connect, TLS, TTFB, download)
41
+ - Resource sizes
42
+ - Failed requests and errors
43
+
44
+ ### `resources/`
45
+
46
+ **Resources directory** - Cached resources:
47
+ - Images, fonts, stylesheets, scripts
48
+ - Response bodies for replay
49
+ - Assets needed to reconstruct page state
50
+
51
+ ## What Traces Capture
52
+
53
+ | Category | Details |
54
+ |----------|---------|
55
+ | **Actions** | Clicks, fills, hovers, keyboard input, navigations |
56
+ | **DOM** | Full DOM snapshot before/after each action |
57
+ | **Screenshots** | Visual state at each step |
58
+ | **Network** | All requests, responses, headers, bodies, timing |
59
+ | **Console** | All console.log, warn, error messages |
60
+ | **Timing** | Precise timing for each operation |
61
+
62
+ ## Use Cases
63
+
64
+ ### Debugging Failed Actions
65
+
66
+ ```bash
67
+ playwright-cli tracing-start
68
+ playwright-cli open https://app.example.com
69
+
70
+ # This click fails - why?
71
+ playwright-cli click e5
72
+
73
+ playwright-cli tracing-stop
74
+ # Open trace to see DOM state when click was attempted
75
+ ```
76
+
77
+ ### Analyzing Performance
78
+
79
+ ```bash
80
+ playwright-cli tracing-start
81
+ playwright-cli open https://slow-site.com
82
+ playwright-cli tracing-stop
83
+
84
+ # View network waterfall to identify slow resources
85
+ ```
86
+
87
+ ### Capturing Evidence
88
+
89
+ ```bash
90
+ # Record a complete user flow for documentation
91
+ playwright-cli tracing-start
92
+
93
+ playwright-cli open https://app.example.com/checkout
94
+ playwright-cli fill e1 "4111111111111111"
95
+ playwright-cli fill e2 "12/25"
96
+ playwright-cli fill e3 "123"
97
+ playwright-cli click e4
98
+
99
+ playwright-cli tracing-stop
100
+ # Trace shows exact sequence of events
101
+ ```
102
+
103
+ ## Trace vs Video vs Screenshot
104
+
105
+ | Feature | Trace | Video | Screenshot |
106
+ |---------|-------|-------|------------|
107
+ | **Format** | .trace file | .webm video | .png/.jpeg image |
108
+ | **DOM inspection** | Yes | No | No |
109
+ | **Network details** | Yes | No | No |
110
+ | **Step-by-step replay** | Yes | Continuous | Single frame |
111
+ | **File size** | Medium | Large | Small |
112
+ | **Best for** | Debugging | Demos | Quick capture |
113
+
114
+ ## Best Practices
115
+
116
+ ### 1. Start Tracing Before the Problem
117
+
118
+ ```bash
119
+ # Trace the entire flow, not just the failing step
120
+ playwright-cli tracing-start
121
+ playwright-cli open https://example.com
122
+ # ... all steps leading to the issue ...
123
+ playwright-cli tracing-stop
124
+ ```
125
+
126
+ ### 2. Clean Up Old Traces
127
+
128
+ Traces can consume significant disk space:
129
+
130
+ ```bash
131
+ # Remove traces older than 7 days
132
+ find .playwright-cli/traces -mtime +7 -delete
133
+ ```
134
+
135
+ ## Limitations
136
+
137
+ - Traces add overhead to automation
138
+ - Large traces can consume significant disk space
139
+ - Some dynamic content may not replay perfectly
@@ -0,0 +1,143 @@
1
+ # Video Recording
2
+
3
+ Capture browser automation sessions as video for debugging, documentation, or verification. Produces WebM (VP8/VP9 codec).
4
+
5
+ ## Basic Recording
6
+
7
+ ```bash
8
+ # Open browser first
9
+ playwright-cli open
10
+
11
+ # Start recording
12
+ playwright-cli video-start demo.webm
13
+
14
+ # Add a chapter marker for section transitions
15
+ playwright-cli video-chapter "Getting Started" --description="Opening the homepage" --duration=2000
16
+
17
+ # Navigate and perform actions
18
+ playwright-cli goto https://example.com
19
+ playwright-cli snapshot
20
+ playwright-cli click e1
21
+
22
+ # Add another chapter
23
+ playwright-cli video-chapter "Filling Form" --description="Entering test data" --duration=2000
24
+ playwright-cli fill e2 "test input"
25
+
26
+ # Stop and save
27
+ playwright-cli video-stop
28
+ ```
29
+
30
+ ## Best Practices
31
+
32
+ ### 1. Use Descriptive Filenames
33
+
34
+ ```bash
35
+ # Include context in filename
36
+ playwright-cli video-start recordings/login-flow-2024-01-15.webm
37
+ playwright-cli video-start recordings/checkout-test-run-42.webm
38
+ ```
39
+
40
+ ### 2. Record entire hero scripts.
41
+
42
+ When recording a video for the user or as a proof of work, it is best to create a code snippet and execute it with run-code.
43
+ It allows inserting appropriate pauses between the actions and annotating the video. There are new Playwright APIs for that.
44
+
45
+ 1) Perform scenario using CLI and take note of all locators and actions. You'll need those locators to request their bounding boxes for highlight.
46
+ 2) Create a file with the intended script for video (below). Use pressSequentially w/ delay for nice typing, make reasonable pauses.
47
+ 3) Use playwright-cli run-code --filename your-script.js
48
+
49
+ **Important**: Overlays are `pointer-events: none` — they do not interfere with page interactions. You can safely keep sticky overlays visible while clicking, filling, or performing any actions on the page.
50
+
51
+ ```js
52
+ async page => {
53
+ await page.screencast.start({ path: 'video.webm', size: { width: 1280, height: 800 } });
54
+ await page.goto('https://demo.playwright.dev/todomvc');
55
+
56
+ // Show a chapter card — blurs the page and shows a dialog.
57
+ // Blocks until duration expires, then auto-removes.
58
+ // Use this for simple use cases, but always feel free to hand-craft your own beautiful
59
+ // overlay via await page.screencast.showOverlay().
60
+ await page.screencast.showChapter('Adding Todo Items', {
61
+ description: 'We will add several items to the todo list.',
62
+ duration: 2000,
63
+ });
64
+
65
+ // Perform action
66
+ await page.getByRole('textbox', { name: 'What needs to be done?' }).pressSequentially('Walk the dog', { delay: 60 });
67
+ await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter');
68
+ await page.waitForTimeout(1000);
69
+
70
+ // Show next chapter
71
+ await page.screencast.showChapter('Verifying Results', {
72
+ description: 'Checking the item appeared in the list.',
73
+ duration: 2000,
74
+ });
75
+
76
+ // Add a sticky annotation that stays while you perform actions.
77
+ // Overlays are pointer-events: none, so they won't block clicks.
78
+ const annotation = await page.screencast.showOverlay(`
79
+ <div style="position: absolute; top: 8px; right: 8px;
80
+ padding: 6px 12px; background: rgba(0,0,0,0.7);
81
+ border-radius: 8px; font-size: 13px; color: white;">
82
+ ✓ Item added successfully
83
+ </div>
84
+ `);
85
+
86
+ // Perform more actions while the annotation is visible
87
+ await page.getByRole('textbox', { name: 'What needs to be done?' }).pressSequentially('Buy groceries', { delay: 60 });
88
+ await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter');
89
+ await page.waitForTimeout(1500);
90
+
91
+ // Remove the annotation when done
92
+ await annotation.dispose();
93
+
94
+ // You can also highlight relevant locators and provide contextual annotations.
95
+ const bounds = await page.getByText('Walk the dog').boundingBox();
96
+ await page.screencast.showOverlay(`
97
+ <div style="position: absolute;
98
+ top: ${bounds.y}px;
99
+ left: ${bounds.x}px;
100
+ width: ${bounds.width}px;
101
+ height: ${bounds.height}px;
102
+ border: 1px solid red;">
103
+ </div>
104
+ <div style="position: absolute;
105
+ top: ${bounds.y + bounds.height + 5}px;
106
+ left: ${bounds.x + bounds.width / 2}px;
107
+ transform: translateX(-50%);
108
+ padding: 6px;
109
+ background: #808080;
110
+ border-radius: 10px;
111
+ font-size: 14px;
112
+ color: white;">Check it out, it is right above this text
113
+ </div>
114
+ `, { duration: 2000 });
115
+
116
+ await page.screencast.stop();
117
+ }
118
+ ```
119
+
120
+ Embrace creativity, overlays are powerful.
121
+
122
+ ### Overlay API Summary
123
+
124
+ | Method | Use Case |
125
+ |--------|----------|
126
+ | `page.screencast.showChapter(title, { description?, duration?, styleSheet? })` | Full-screen chapter card with blurred backdrop — ideal for section transitions |
127
+ | `page.screencast.showOverlay(html, { duration? })` | Custom HTML overlay — use for callouts, labels, highlights |
128
+ | `disposable.dispose()` | Remove a sticky overlay added without duration |
129
+ | `page.screencast.hideOverlays()` / `page.screencast.showOverlays()` | Temporarily hide/show all overlays |
130
+
131
+ ## Tracing vs Video
132
+
133
+ | Feature | Video | Tracing |
134
+ |---------|-------|---------|
135
+ | Output | WebM file | Trace file (viewable in Trace Viewer) |
136
+ | Shows | Visual recording | DOM snapshots, network, console, actions |
137
+ | Use case | Demos, documentation | Debugging, analysis |
138
+ | Size | Larger | Smaller |
139
+
140
+ ## Limitations
141
+
142
+ - Recording adds slight overhead to automation
143
+ - Large recordings can consume significant disk space
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: playwright-cli-mini
3
+ description: Automate browser interactions, test web pages and work with Playwright tests.
4
+ ---
5
+
6
+ # Browser Automation with playwright-cli
7
+
8
+ ## Quick start
9
+
10
+ ```bash
11
+ # open new browser in headed mode
12
+ playwright-cli open --headed
13
+ # navigate to a page
14
+ playwright-cli goto https://playwright.dev
15
+ # take a snapshot
16
+ playwright-cli snapshot
17
+ # interact with the page using refs from the snapshot
18
+ playwright-cli click e15
19
+ playwright-cli type "page.click"
20
+ playwright-cli press Enter
21
+ # close the browser
22
+ playwright-cli close
23
+ ```
24
+
25
+ ## Commands
26
+
27
+ ### Core
28
+
29
+ ```bash
30
+ playwright-cli open https://example.com/ --headed
31
+ playwright-cli goto https://playwright.dev
32
+ playwright-cli type "search query"
33
+ playwright-cli click e3
34
+ playwright-cli dblclick e7
35
+ # --submit presses Enter after filling the element
36
+ playwright-cli fill e5 "user@example.com" --submit
37
+ # search the snapshot for text or a regexp, returns matching nodes with surrounding context
38
+ playwright-cli find "Sign in"
39
+ playwright-cli find --regex "Sign (in|up)"
40
+ # wrap the regexp in slashes to add flags, e.g. /i for case-insensitive
41
+ playwright-cli find --regex "/sign (in|up)/i"
42
+ playwright-cli eval "document.title"
43
+ playwright-cli eval "el => el.textContent" e5
44
+ # get element id, class, or any attribute not visible in the snapshot
45
+ playwright-cli eval "el => el.id" e5
46
+ playwright-cli eval "el => el.getAttribute('data-testid')" e5
47
+ playwright-cli dialog-accept
48
+ playwright-cli dialog-accept "confirmation text"
49
+ playwright-cli dialog-dismiss
50
+ playwright-cli resize 1920 1080
51
+ playwright-cli close
52
+ ```
53
+
54
+ ### Navigation
55
+
56
+ ```bash
57
+ playwright-cli go-back
58
+ playwright-cli go-forward
59
+ playwright-cli reload
60
+ ```
61
+
62
+ ### Keyboard
63
+
64
+ ```bash
65
+ playwright-cli press Enter
66
+ playwright-cli press ArrowDown
67
+ playwright-cli keydown Shift
68
+ playwright-cli keyup Shift
69
+ ```
70
+
71
+ ### Mouse
72
+
73
+ ```bash
74
+ playwright-cli mousemove 150 300
75
+ playwright-cli mousedown
76
+ playwright-cli mousedown right
77
+ playwright-cli mouseup
78
+ playwright-cli mouseup right
79
+ playwright-cli mousewheel 0 100
80
+ ```
81
+
82
+ ### DevTools
83
+
84
+ ```bash
85
+ playwright-cli console
86
+ playwright-cli console warning
87
+ playwright-cli requests
88
+ playwright-cli request 5
89
+ playwright-cli run-code "async page => await page.context().grantPermissions(['geolocation'])"
90
+ playwright-cli run-code --filename=/workspace/script.js
91
+
92
+ # launch the dashboard for UI review / design feedback — user annotates the page, you receive the annotated screenshot, snapshot, and notes
93
+ playwright-cli show --annotate
94
+
95
+ # generate a Playwright locator for an element from its ref or selector
96
+ playwright-cli generate-locator e5 --raw
97
+
98
+ # show a persistent highlight overlay for an element, optionally with a custom style
99
+ playwright-cli highlight e5
100
+ playwright-cli highlight e5 --style="outline: 3px dashed red"
101
+ # hide a single element highlight, or all page highlights when no target is given
102
+ playwright-cli highlight e5 --hide
103
+ playwright-cli highlight --hide
104
+ ```
105
+
106
+ ## Snapshots
107
+
108
+ ```bash
109
+ playwright-cli snapshot --filename=/workspace/after-click.yaml
110
+
111
+ # snapshot an element instead of the whole page
112
+ playwright-cli snapshot "#main"
113
+
114
+ # limit snapshot depth for efficiency, take a partial snapshot afterwards
115
+ playwright-cli snapshot --depth=4
116
+ playwright-cli snapshot e34
117
+
118
+ # include each element's bounding box as [box=x,y,width,height]
119
+ playwright-cli snapshot --boxes
120
+
121
+ # search a large snapshot instead of capturing it all — returns matching nodes
122
+ # with 3 lines of context around each match (like grep -C)
123
+ playwright-cli find "Add to cart"
124
+ playwright-cli find --regex "\\$[0-9]+\\.[0-9]{2}"
125
+ ```
126
+
127
+ ## Targeting elements
128
+
129
+ By default, use refs from the snapshot to interact with page elements.
130
+
131
+ ```bash
132
+ # get snapshot with refs
133
+ playwright-cli snapshot
134
+
135
+ # interact using a ref
136
+ playwright-cli click e15
137
+ ```
138
+
139
+ You can also use css selectors or Playwright locators.
140
+
141
+ ```bash
142
+ # css selector
143
+ playwright-cli click "#main > button.submit"
144
+
145
+ # role locator
146
+ playwright-cli click "getByRole('button', { name: 'Submit' })"
147
+
148
+ # test id
149
+ playwright-cli click "getByTestId('submit-button')"
150
+ ```
151
+
152
+ ## Interactive session
153
+
154
+ Use this to interact with the user.
155
+
156
+ ```bash
157
+ playwright-cli open https://example.com
158
+ # show something to the user
159
+ playwright-cli show
160
+ # perform actions that the user will see ...
161
+
162
+ # or ask the user to point at something
163
+ playwright-cli show --annotate
164
+ ```
@@ -0,0 +1,23 @@
1
+ # Inspecting Element Attributes
2
+
3
+ When the snapshot doesn't show an element's `id`, `class`, `data-*` attributes, or other DOM properties, use `eval` to inspect them.
4
+
5
+ ## Examples
6
+
7
+ ```bash
8
+ playwright-cli snapshot
9
+ # snapshot shows a button as e7 but doesn't reveal its id or data attributes
10
+
11
+ # get the element's id
12
+ playwright-cli eval "el => el.id" e7
13
+
14
+ # get all CSS classes
15
+ playwright-cli eval "el => el.className" e7
16
+
17
+ # get a specific attribute
18
+ playwright-cli eval "el => el.getAttribute('data-testid')" e7
19
+ playwright-cli eval "el => el.getAttribute('aria-label')" e7
20
+
21
+ # get a computed style property
22
+ playwright-cli eval "el => getComputedStyle(el).display" e7
23
+ ```
@@ -0,0 +1,39 @@
1
+ # Running Playwright Tests
2
+
3
+ To run Playwright tests, use the `npx playwright test` command, or a package manager script. To avoid opening the interactive html report, use `PLAYWRIGHT_HTML_OPEN=never` environment variable.
4
+
5
+ ```bash
6
+ # Run all tests
7
+ PLAYWRIGHT_HTML_OPEN=never npx playwright test
8
+
9
+ # Run all tests through a custom npm script
10
+ PLAYWRIGHT_HTML_OPEN=never npm run special-test-command
11
+ ```
12
+
13
+ # Debugging Playwright Tests
14
+
15
+ To debug a failing Playwright test, run it with `--debug=cli` option. This command will pause the test at the start and print the debugging instructions.
16
+
17
+ **IMPORTANT**: run the command in the background and check the output until "Debugging Instructions" is printed. Make sure to stop the command after you have finished.
18
+
19
+ Once instructions containing a session name are printed, use `playwright-cli` to attach the session and explore the page.
20
+
21
+ ```bash
22
+ # Run the test
23
+ PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli
24
+ # ...
25
+ # ... debugging instructions for "tw-abcdef" session ...
26
+ # ...
27
+
28
+ # Attach to the test
29
+ playwright-cli attach tw-abcdef
30
+ ```
31
+
32
+ Keep the test running in the background while you explore and look for a fix.
33
+ The test is paused at the start, so you should step over or pause at a particular location
34
+ where the problem is most likely to be.
35
+
36
+ Every action you perform with `playwright-cli` generates corresponding Playwright TypeScript code.
37
+ This code appears in the output and can be copied directly into the test. Most of the time, a specific locator or an expectation should be updated, but it could also be a bug in the app. Use your judgement.
38
+
39
+ After fixing the test, stop the background test run. Rerun to check that test passes.
@@ -0,0 +1,87 @@
1
+ # Request Mocking
2
+
3
+ Intercept, mock, modify, and block network requests.
4
+
5
+ ## CLI Route Commands
6
+
7
+ ```bash
8
+ # Mock with custom status
9
+ playwright-cli route "**/*.jpg" --status=404
10
+
11
+ # Mock with JSON body
12
+ playwright-cli route "**/api/users" --body='[{"id":1,"name":"Alice"}]' --content-type=application/json
13
+
14
+ # Mock with custom headers
15
+ playwright-cli route "**/api/data" --body='{"ok":true}' --header="X-Custom: value"
16
+
17
+ # Remove headers from requests
18
+ playwright-cli route "**/*" --remove-header=cookie,authorization
19
+
20
+ # List active routes
21
+ playwright-cli route-list
22
+
23
+ # Remove a route or all routes
24
+ playwright-cli unroute "**/*.jpg"
25
+ playwright-cli unroute
26
+ ```
27
+
28
+ ## URL Patterns
29
+
30
+ ```
31
+ **/api/users - Exact path match
32
+ **/api/*/details - Wildcard in path
33
+ **/*.{png,jpg,jpeg} - Match file extensions
34
+ **/search?q=* - Match query parameters
35
+ ```
36
+
37
+ ## Advanced Mocking with run-code
38
+
39
+ For conditional responses, request body inspection, response modification, or delays:
40
+
41
+ ### Conditional Response Based on Request
42
+
43
+ ```bash
44
+ playwright-cli run-code "async page => {
45
+ await page.route('**/api/login', route => {
46
+ const body = route.request().postDataJSON();
47
+ if (body.username === 'admin') {
48
+ route.fulfill({ body: JSON.stringify({ token: 'mock-token' }) });
49
+ } else {
50
+ route.fulfill({ status: 401, body: JSON.stringify({ error: 'Invalid' }) });
51
+ }
52
+ });
53
+ }"
54
+ ```
55
+
56
+ ### Modify Real Response
57
+
58
+ ```bash
59
+ playwright-cli run-code "async page => {
60
+ await page.route('**/api/user', async route => {
61
+ const response = await route.fetch();
62
+ const json = await response.json();
63
+ json.isPremium = true;
64
+ await route.fulfill({ response, json });
65
+ });
66
+ }"
67
+ ```
68
+
69
+ ### Simulate Network Failures
70
+
71
+ ```bash
72
+ playwright-cli run-code "async page => {
73
+ await page.route('**/api/offline', route => route.abort('internetdisconnected'));
74
+ }"
75
+ # Options: connectionrefused, timedout, connectionreset, internetdisconnected
76
+ ```
77
+
78
+ ### Delayed Response
79
+
80
+ ```bash
81
+ playwright-cli run-code "async page => {
82
+ await page.route('**/api/slow', async route => {
83
+ await new Promise(r => setTimeout(r, 3000));
84
+ route.fulfill({ body: JSON.stringify({ data: 'loaded' }) });
85
+ });
86
+ }"
87
+ ```