Skip to content

Commit 36e6a34

Browse files
gandhi-21Gaurav Gandhi
and
Gaurav Gandhi
authored
test(qdoc): Add ui tests for qdoc update readme flow (#5435)
Add UI tests to validate the Update an existing README flow Created a sample repository from scratch, For Update README to reflect code flow, there are 3 tests which confirm that the user is Shown the option to confirm / change folder / cancel on selecting the update options Shown the Update with specific changes flow when selecting Make Changes upon getting updated readme back The Readme updates with the latest changes For Make a specific change flow, there are 2 tests which confirm that the user is Shown the Update with specific changes flow when selecting Make Changes upon getting updated readme back The Readme is updated with the specific changes requested * test(qdoc): initial tests for latest code changes flow * update tstData to test * update scripts + move test data to subfolder for update readme tests * update instructions in update readme with specific changes test * update base readme for testing the update readme flow * update test assertions for q doc update flow tests * separate out test cases into individual tests * remove gradle settings file for q doc update flow test repo * log result from scripts for debugging * manually restore readme after each test run * add end of assertions println for debugging + update readme * update q tests config for debugging * update config and rename dummy repo files for create readme tests * update build file for create readme tests sample repo * update to print the result on failures only * remove unused file from test dummy repo --------- Co-authored-by: Gaurav Gandhi <gangaur@amazon.com>
1 parent cb6daca commit 36e6a34

File tree

13 files changed

+979
-0
lines changed

13 files changed

+979
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.uitests.docTests
5+
6+
import java.nio.file.Paths
7+
8+
fun prepTestData(isCreate: Boolean) {
9+
val process: Process
10+
if (isCreate) {
11+
val path = Paths.get("tstData", "qdoc", "createFlow", "README.md").toUri()
12+
process = ProcessBuilder("rm", path.path).start()
13+
} else {
14+
val path = Paths.get("tstData", "qdoc", "updateFlow", "README.md").toUri()
15+
process = ProcessBuilder("git", "restore", path.path).start()
16+
}
17+
18+
val exitCode = process.waitFor()
19+
if (exitCode != 0) {
20+
println("Warning: git stash command failed with exit code $exitCode")
21+
process.errorStream.bufferedReader().use { reader ->
22+
println("Error: ${reader.readText()}")
23+
}
24+
}
25+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.uitests.docTests.scripts
5+
6+
// language=TS
7+
val findAndClickButtonScript = """
8+
const findAndClickButton = async (
9+
page,
10+
buttonText,
11+
clickButton = false,
12+
timeout = 5000
13+
) => {
14+
try {
15+
// Wait for any matching buttons to be present
16+
await page.waitForSelector('button.mynah-button', {
17+
visible: true,
18+
timeout,
19+
});
20+
21+
// Find and verify the specific button
22+
const buttonHandle = await page.evaluateHandle(text => {
23+
const buttons = Array.from(
24+
document.querySelectorAll('button.mynah-button')
25+
);
26+
return buttons.find(button => {
27+
const label = button.querySelector('.mynah-button-label');
28+
return label && label.textContent.trim() === text;
29+
});
30+
}, buttonText);
31+
32+
// Check if button was found
33+
const button = buttonHandle.asElement();
34+
if (!button) {
35+
console.log(buttonText);
36+
throw new Error(`Button with text not found`);
37+
}
38+
39+
// Verify button is visible and enabled
40+
const isVisible = await page.evaluate(el => {
41+
const style = window.getComputedStyle(el);
42+
return (
43+
style.display !== 'none' &&
44+
style.visibility !== 'hidden' &&
45+
style.opacity !== '0'
46+
);
47+
}, button);
48+
49+
if (!isVisible) {
50+
console.log(buttonText);
51+
throw new Error(`Button with text is not visible`);
52+
}
53+
54+
if (clickButton) {
55+
// Click the button
56+
await button.click();
57+
58+
// Optional wait after click
59+
await new Promise(resolve => setTimeout(resolve, 1000));
60+
61+
console.log(`Successfully clicked button with text`);
62+
console.log(buttonText);
63+
} else {
64+
return button;
65+
}
66+
} catch (error) {
67+
console.error(`Error interacting with button:`, buttonText, error);
68+
throw error;
69+
}
70+
};
71+
""".trimIndent()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.uitests.docTests.scripts
5+
6+
// language=TS
7+
val updateReadmeLatestChangesConfirmOptionsScript = """
8+
const puppeteer = require('puppeteer');
9+
10+
async function testNavigation() {
11+
const browser = await puppeteer.connect({
12+
browserURL: 'http://localhost:9222'
13+
})
14+
15+
try {
16+
17+
const pages = await browser.pages()
18+
19+
for(const page of pages) {
20+
const contents = await page.evaluate(el => el.innerHTML, await page.${'$'}(':root'));
21+
22+
const element = await page.${'$'}('.mynah-chat-prompt-input')
23+
if(element) {
24+
25+
console.log('Typing /doc in the chat window')
26+
27+
await page.type('.mynah-chat-prompt-input', '/doc')
28+
await page.keyboard.press('Enter')
29+
30+
console.log('Attempting to find and click Update an existing README button')
31+
await findAndClickButton(page, 'Update an existing README', true, 10000)
32+
console.log('Attempting to find and click Update README to reflect code button')
33+
await findAndClickButton(page, 'Update README to reflect code', true, 10000)
34+
console.log('Attempting to find all available buttons')
35+
const yesButton = await findAndClickButton(page, 'Yes', false, 10000)
36+
const changeFolderButton = await findAndClickButton(page, 'Change folder', false, 10000)
37+
const cancelButton = await findAndClickButton(page, 'Cancel', false, 10000)
38+
39+
if (!yesButton || !changeFolderButton || !cancelButton) {
40+
console.log('Error: Test Failed')
41+
console.log('Unable to find buttons for Yes/ChangeFolder/Cancel')
42+
} else {
43+
console.log('Found all expected buttons')
44+
console.log('Test Successful')
45+
}
46+
}
47+
}
48+
49+
} finally {
50+
await browser.close();
51+
}
52+
}
53+
54+
testNavigation().catch((error) => {
55+
console.log('Error: Test Failed');
56+
console.error(error);
57+
});
58+
""".trimIndent()
59+
60+
// language=TS
61+
val updateReadmeLatestChangesScript = """
62+
63+
const puppeteer = require('puppeteer');
64+
65+
async function testNavigation() {
66+
const browser = await puppeteer.connect({
67+
browserURL: 'http://localhost:9222'
68+
})
69+
70+
try {
71+
72+
const pages = await browser.pages()
73+
74+
for(const page of pages) {
75+
const contents = await page.evaluate(el => el.innerHTML, await page.${'$'}(':root'));
76+
77+
const element = await page.${'$'}('.mynah-chat-prompt-input')
78+
79+
if(element) {
80+
81+
console.log('Typing /doc in the chat window')
82+
83+
await page.type('.mynah-chat-prompt-input', '/doc')
84+
await page.keyboard.press('Enter')
85+
86+
console.log('Attempting to find and click Update an existing README button')
87+
await findAndClickButton(page, 'Update an existing README', true, 10000)
88+
console.log('Attempting to find and click Update README to reflect code button')
89+
await findAndClickButton(page, 'Update README to reflect code', true, 10000)
90+
console.log('Attempting to find and click Yes button to confirm option')
91+
await findAndClickButton(page, 'Yes', true, 10000)
92+
console.log('Waiting for updated README to be generated')
93+
await new Promise(resolve => setTimeout(resolve, 90000));
94+
console.log('Attempting to find and click Accept button')
95+
await findAndClickButton(page, 'Accept', true, 10000)
96+
}
97+
}
98+
99+
} finally {
100+
await browser.close();
101+
}
102+
}
103+
104+
testNavigation().catch((error) => {
105+
console.log('Error: Test Failed');
106+
console.error(error);
107+
});
108+
109+
""".trimIndent()
110+
111+
// language=TS
112+
val updateReadmeLatestChangesMakeChangesFlowScript = """
113+
114+
const puppeteer = require('puppeteer');
115+
116+
async function testNavigation() {
117+
const browser = await puppeteer.connect({
118+
browserURL: 'http://localhost:9222'
119+
});
120+
121+
try {
122+
123+
const pages = await browser.pages();
124+
125+
for(const page of pages) {
126+
const contents = await page.evaluate(el => el.innerHTML, await page.${'$'}(':root'));
127+
128+
const element = await page.${'$'}('.mynah-chat-prompt-input');
129+
if(element) {
130+
131+
console.log('Typing /doc in the chat window');
132+
133+
await page.type('.mynah-chat-prompt-input', '/doc');
134+
await page.keyboard.press('Enter');
135+
136+
console.log('Attempting to find and click Update an existing README button');
137+
await findAndClickButton(page, 'Update an existing README', true, 10000);
138+
console.log('Attempting to find and click Update README to reflect code button');
139+
await findAndClickButton(page, 'Update README to reflect code', true, 10000);
140+
console.log('Attempting to find and click Yes button to confirm option');
141+
await findAndClickButton(page, 'Yes', true, 10000);
142+
console.log('Waiting for updated README to be generated');
143+
await new Promise(resolve => setTimeout(resolve, 90000));
144+
console.log('Attempting to find and click Make changes button');
145+
await findAndClickButton(page, 'Make changes', true, 10000);
146+
const makeChangeText = await page.waitForSelector('[placeholder="Describe documentation changes"]');
147+
if (!makeChangeText) {
148+
console.log('Error: Test Failed');
149+
console.log('Unable to find placeholder description test in Make Changes flow');
150+
} else {
151+
console.log('Found expected placeholder text for Make Changes flow');
152+
console.log('Test Successful');
153+
}
154+
155+
}
156+
}
157+
158+
} finally {
159+
await browser.close();
160+
}
161+
}
162+
163+
testNavigation().catch((error) => {
164+
console.log('Error: Test Failed');
165+
console.error(error);
166+
});
167+
168+
""".trimIndent()
169+
170+
val updateReadmeLatestChangesConfirmOptionsTestScript = updateReadmeLatestChangesConfirmOptionsScript.plus(findAndClickButtonScript)
171+
val updateReadmeLatestChangesTestScript = updateReadmeLatestChangesScript.plus(findAndClickButtonScript)
172+
val updateReadmeLatestChangesMakeChangesFlowTestScript = updateReadmeLatestChangesMakeChangesFlowScript.plus(findAndClickButtonScript)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.uitests.docTests.scripts
5+
6+
// language=TS
7+
val updateReadmeSpecificChangesMakeChangesFlowScript = """
8+
9+
const puppeteer = require('puppeteer');
10+
11+
async function testNavigation() {
12+
const browser = await puppeteer.connect({
13+
browserURL: 'http://localhost:9222'
14+
});
15+
16+
try {
17+
18+
const pages = await browser.pages();
19+
20+
for(const page of pages) {
21+
const contents = await page.evaluate(el => el.innerHTML, await page.${'$'}(':root'));
22+
23+
const element = await page.${'$'}('.mynah-chat-prompt-input');
24+
if(element) {
25+
26+
console.log('Typing /doc in the chat window');
27+
28+
await page.type('.mynah-chat-prompt-input', '/doc');
29+
await page.keyboard.press('Enter');
30+
31+
console.log('Attempting to find and click Update an existing README button');
32+
await findAndClickButton(page, 'Update an existing README', true, 10000);
33+
console.log('Attempting to find and click Make a specific change button');
34+
await findAndClickButton(page, 'Make a specific change', true, 10000);
35+
console.log('Attempting to find and click Yes button to confirm option');
36+
await findAndClickButton(page, 'Yes', true, 10000);
37+
38+
console.log('Typing specific change instructions in the chat window');
39+
await page.type('.mynah-chat-prompt-input', 'Add a section with Installation instructions for this repository. Title this new section \"### Installation\"');
40+
await page.keyboard.press('Enter');
41+
42+
console.log('Waiting for updated README to be generated');
43+
await new Promise(resolve => setTimeout(resolve, 90000));
44+
console.log('Attempting to find and click Make changes button');
45+
await findAndClickButton(page, 'Make changes', true, 10000);
46+
const makeChangeText = await page.waitForSelector('[placeholder="Describe documentation changes"]');
47+
if (!makeChangeText) {
48+
console.log('Error: Test Failed');
49+
console.log('Unable to find placeholder description text in Make Changes flow');
50+
} else {
51+
console.log('Found expected placeholder text for Make Changes flow');
52+
console.log('Test Successful');
53+
}
54+
55+
}
56+
}
57+
58+
} finally {
59+
await browser.close();
60+
}
61+
}
62+
63+
testNavigation().catch((error) => {
64+
console.log('Error: Test Failed');
65+
console.error(error);
66+
});
67+
68+
""".trimIndent()
69+
70+
// language=TS
71+
val updateReadmeSpecificChangesScript = """
72+
73+
const puppeteer = require('puppeteer');
74+
75+
async function testNavigation() {
76+
const browser = await puppeteer.connect({
77+
browserURL: 'http://localhost:9222'
78+
});
79+
80+
try {
81+
82+
const pages = await browser.pages();
83+
84+
for(const page of pages) {
85+
const contents = await page.evaluate(el => el.innerHTML, await page.${'$'}(':root'));
86+
87+
const element = await page.${'$'}('.mynah-chat-prompt-input');
88+
89+
if(element) {
90+
91+
console.log('Typing /doc in the chat window');
92+
93+
await page.type('.mynah-chat-prompt-input', '/doc');
94+
await page.keyboard.press('Enter');
95+
96+
console.log('Attempting to find and click Update an existing README button');
97+
await findAndClickButton(page, 'Update an existing README', true, 10000);
98+
console.log('Attempting to find and click Make a specific change button');
99+
await findAndClickButton(page, 'Make a specific change', true, 10000);
100+
console.log('Attempting to find and click Yes button to confirm option');
101+
await findAndClickButton(page, 'Yes', true, 10000);
102+
103+
console.log('Typing specific change instructions in the chat window');
104+
await page.type('.mynah-chat-prompt-input', 'Add a section with Installation instructions for this repository. Title this new section \"### Installation\"');
105+
await page.keyboard.press('Enter');
106+
107+
console.log('Waiting for updated README to be generated');
108+
await new Promise(resolve => setTimeout(resolve, 90000));
109+
110+
console.log('Attempting to find and click Accept button');
111+
await findAndClickButton(page, 'Accept', true, 10000);
112+
}
113+
}
114+
115+
} finally {
116+
await browser.close();
117+
}
118+
}
119+
120+
testNavigation().catch((error) => {
121+
console.log('Error: Test Failed');
122+
console.error(error);
123+
});
124+
125+
""".trimIndent()
126+
127+
val updateReadmeSpecificChangesMakeChangesFlowTestScript = updateReadmeSpecificChangesMakeChangesFlowScript.plus(findAndClickButtonScript)
128+
val updateReadmeSpecificChangesTestScript = updateReadmeSpecificChangesScript.plus(findAndClickButtonScript)

0 commit comments

Comments
 (0)