Skip to content

Commit 2d4840b

Browse files
authored
Merge pull request #12 from xerris/expected-error-scenario/gitesh
Expected error scenario/gitesh
2 parents c1e62a5 + 5f692a3 commit 2d4840b

File tree

7 files changed

+121
-83
lines changed

7 files changed

+121
-83
lines changed
Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
11
@Hoist @Rope-Record
22
Feature: Rope Records
33

4-
Scenario: Add new rope
5-
Given I navigate to the Rope record page
6-
And I add a new rope
7-
And I provide the following rope information - greg
8-
| Rope type | Head rope |
9-
| Hoist # | 1 |
10-
| Serial number | CUCSNO123 |
11-
| Diameter of rope (optional) | 1234 |
12-
| Weight of rope | 123 |
13-
| Construction of rope | abcd |
14-
| Type of lay | N/A |
15-
| Grade of steel | 1234 |
16-
| Manufacturer name | zyx inc |
17-
| Manufacturer address | xyz street |
18-
| Manufacture date | Dec 19, 2018 |
19-
| Class of core used in the rope | 123 |
20-
| Number of strands in the rope | 123 |
21-
| Number of wires in each strand | 123 |
22-
| Diameter of wires | 123 |
23-
| Breaking stress of steel | 123 |
24-
| Standard torsion test of the | 123 |
25-
| The percentage by mass of | 123 |
26-
| The trade name of the | trade-name |
27-
| Breaking load | 123 |
28-
| Test number | 12 |
29-
| Test date | Dec 19, 2024 |
30-
When I click on Save
31-
Then I should be able to navigate to the Rope Detail Page for created rope
4+
Background:
5+
6+
Scenario: Add a new rope with a unique serial number and validate duplicate error
7+
Given I navigate to the Rope record page
8+
And I add a new rope
9+
And I provide the following rope information with "Unique" serial number
10+
| Rope type | Head rope |
11+
| Hoist # | 1 |
12+
| Serial number | <unique> | # Dynamically generated serial number
13+
| Diameter of rope (optional) | 1234 |
14+
| Weight of rope | 123 |
15+
| Construction of rope | abcd |
16+
| Type of lay | N/A |
17+
| Grade of steel | 1234 |
18+
| Manufacturer name | zyx inc |
19+
| Manufacturer address | xyz street |
20+
| Manufacture date | Dec 19, 2018 |
21+
| Class of core used in the rope | 123 |
22+
| Number of strands in the rope | 123 |
23+
| Number of wires in each strand | 123 |
24+
| Diameter of wires | 123 |
25+
| Breaking stress of steel | 123 |
26+
| Standard torsion test of the | 123 |
27+
| The percentage by mass of | 123 |
28+
| The trade name of the | trade-name |
29+
| Breaking load | 123 |
30+
| Test number | 12 |
31+
| Test date | Dec 19, 2024 |
32+
When I click on Save
33+
Then I should be able to navigate to the Rope Detail Page for created rope
34+
35+
Given I navigate to the Rope record page
36+
And I add a new rope
37+
And I reuse the same serial number and rope information from the previous rope
38+
When I click on Save
39+
Then I should get a duplicate serial number error as 'This serial number is already in use'

src/pages/CreateRopeRecord.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@ export class CreateRopeRecord {
5454
await this.formHelper.setField(this.page, fieldName, value, metadata);
5555
}
5656

57-
// Set multiple field values for a specific metadata group
58-
public async setFieldValues(
59-
fields: Record<string, string>,
60-
metadata: FormFieldMetadata[],
61-
): Promise<void> {
62-
for (const [fieldName, value] of Object.entries(fields)) {
63-
await this.setFieldValue(fieldName, value, metadata);
57+
// Central method to fill fields dynamically
58+
public async fillRopeFields(ropeInfo: Record<string, string>): Promise<void> {
59+
// Iterate over the ropeInfo object and set each field dynamically
60+
for (const [fieldName, value] of Object.entries(ropeInfo)) {
61+
await this.setFieldValue(fieldName, value, this.ropeMetadata);
6462
}
6563
}
6664

@@ -96,9 +94,4 @@ export class CreateRopeRecord {
9694
await this.openAccordionTab(tabName);
9795
}
9896
}
99-
100-
// Set field values for specific metadata groups
101-
public async setRopeInformation(fields: Record<string, string>) {
102-
await this.setFieldValues(fields, this.ropeMetadata);
103-
}
10497
}
Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DataTable, Given, When } from '@cucumber/cucumber';
1+
import { DataTable, Given, Then, When } from '@cucumber/cucumber';
22

33
import { CreateRopeRecord } from '@/pages/CreateRopeRecord';
44
import { HoistWorld, IHoistWorld } from '@/support/hoist-world';
@@ -12,47 +12,52 @@ Given('I add a new rope', async function (this: IHoistWorld) {
1212
});
1313

1414
Given(
15-
'I provide the following rope information - greg',
16-
async function (this: IHoistWorld, dataTable: DataTable): Promise<void> {
17-
const page = this.page!;
18-
const uniqueGenerator = new UniqueIdentifierGenerator();
19-
const ropeInfo = dataTable.rowsHash();
20-
const ropeRecord = new CreateRopeRecord(page); // Create an instance of CreateRopeRecord
21-
22-
for (const [fieldName, value] of Object.entries(ropeInfo)) {
23-
let cleanValue = value;
24-
25-
// Handle specific fields like Serial number
26-
if (fieldName === 'Serial number') {
27-
cleanValue = uniqueGenerator.generateUniqueValue('CUCSNO', 6); // Generate unique serial number
28-
this.generatedSerialNumber = cleanValue;
29-
HoistWorld.sharedState.generatedSerialNumber = cleanValue;
30-
}
31-
32-
if (!ropeRecord.ropeMetadata) {
33-
throw new Error(`No metadata found for field: ${fieldName}`);
34-
}
35-
36-
// Pass metadata wrapped in an array
37-
await ropeRecord.setFieldValue(fieldName, cleanValue, ropeRecord.ropeMetadata);
15+
'I provide the following rope information with {string} serial number',
16+
async function (
17+
this: IHoistWorld,
18+
serialNumberType: string,
19+
dataTable: DataTable,
20+
): Promise<void> {
21+
const ropeInfo = dataTable.rowsHash(); // Convert Gherkin table to object
22+
const ropeRecord = new CreateRopeRecord(this.page!);
23+
24+
// Generating unique serial and caching it
25+
if (serialNumberType === 'Unique') {
26+
const uniqueSerialNumber = new UniqueIdentifierGenerator().generateUniqueValue('CUCSNO', 6);
27+
ropeInfo['Serial number'] = uniqueSerialNumber;
28+
this.generatedSerialNumber = uniqueSerialNumber;
29+
HoistWorld.sharedState.generatedSerialNumber = uniqueSerialNumber;
3830
}
3931

32+
// Caching ropeInfo
33+
HoistWorld.sharedState.ropeInfo = ropeInfo;
34+
35+
await ropeRecord.fillRopeFields(ropeInfo);
4036
this.ropeRecord = ropeRecord;
41-
await executeWithDelay();
37+
38+
await executeWithDelay(); // Add delay to simulate real-world conditions
4239
},
4340
);
4441

45-
// Define the sleep function
46-
async function sleep(ms: number): Promise<void> {
47-
return new Promise(resolve => setTimeout(resolve, ms));
48-
}
42+
Given(
43+
'I reuse the same serial number and rope information from the previous rope',
44+
async function (this: IHoistWorld) {
45+
if (!this.generatedSerialNumber) {
46+
throw new Error('No previously generated serial number found to reuse.');
47+
}
48+
const ropeRecord = new CreateRopeRecord(this.page!);
4949

50-
// Usage of the sleep function
51-
async function executeWithDelay() {
52-
console.log('Taking a break');
53-
await sleep(5000); // Pause for 5 seconds
54-
console.log('Done');
55-
}
50+
// Reuse the previous ropeInfo
51+
const ropeInfo = HoistWorld.sharedState.ropeInfo ?? {};
52+
53+
// Reuse the previous serial number
54+
ropeInfo['Serial number'] = this.generatedSerialNumber;
55+
56+
// Fill the form with the cached ropeInfo
57+
await ropeRecord.fillRopeFields(ropeInfo);
58+
this.ropeRecord = ropeRecord;
59+
},
60+
);
5661

5762
When('I click on Save', async function (this: IHoistWorld) {
5863
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
@@ -67,3 +72,27 @@ When('I click on Save', async function (this: IHoistWorld) {
6772

6873
await this.page?.getByRole('button', { name: 'Save' }).click();
6974
});
75+
76+
Then(
77+
'I should get a duplicate serial number error as {string}',
78+
async function (this: IHoistWorld, errorMessage: string) {
79+
const page = this.page!;
80+
await page
81+
.locator('div')
82+
.filter({ hasText: errorMessage })
83+
.nth(1)
84+
.waitFor({ state: 'visible', timeout: 180000 });
85+
},
86+
);
87+
88+
// Define the sleep function
89+
async function sleep(ms: number): Promise<void> {
90+
return new Promise(resolve => setTimeout(resolve, ms));
91+
}
92+
93+
// Usage of the sleep function
94+
async function executeWithDelay() {
95+
console.log('Taking a break');
96+
await sleep(5000); // Pause for 5 seconds
97+
console.log('Done');
98+
}

src/steps/rope-record/rope-details/update/em-test.steps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Then('I should be able to see the record in the Records table', async function (
3333
await page.getByRole('button', { name: 'Save', exact: true }).click();
3434

3535
// wait for success notification
36-
await expect(page.getByText('EM test record added')).toBeVisible();
36+
await expect(page.getByText('EM test record added')).toBeVisible({ timeout: 12000 });
3737

3838
// verify saved percent loss
3939
await expect(page.getByRole('main')).toContainText(`${savedPercentLoss}%`);

src/support/FormHelper.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,14 @@ export class FormHelper {
8484
const targetMonth = date.toLocaleString('default', { month: 'long' });
8585
const targetDay = date.getDate().toString();
8686

87-
// click the current selected year in the Date Picker to display the year list
88-
await page.getByRole('button', { name: /^\d{4}$/ }).click();
89-
90-
// then select the target year
91-
await page.getByRole('button', { name: targetYear }).click();
87+
// check if date picker is on our target year
88+
const headerButton = page.locator('button').filter({ hasText: targetYear });
89+
if ((await headerButton.count()) === 0) {
90+
// if not then display the year selection list
91+
await page.getByRole('button', { name: /^\d{4}$/ }).click();
92+
// then select the target year
93+
await page.getByRole('button', { name: targetYear }).click();
94+
}
9295

9396
// we'll be on January. navigate forward until we reach target month
9497
let currentMonth = await page

src/support/hoist-world.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface IHoistWorld extends World {
2828
envConfig: EnvironmentConfig;
2929
ropeRecord?: CreateRopeRecord;
3030
generatedSerialNumber?: string;
31+
ropeInfo?: Record<string, string>;
3132
}
3233
export class HoistWorld extends World implements IHoistWorld {
3334
debug = false;
@@ -39,8 +40,12 @@ export class HoistWorld extends World implements IHoistWorld {
3940
cookies?: Cookie[] = []; // new change
4041
ropeRecord?: CreateRopeRecord;
4142
generatedSerialNumber?: string;
43+
ropeInfo?: Record<string, string>;
4244

43-
static sharedState: { generatedSerialNumber?: string } = {};
45+
static sharedState: {
46+
generatedSerialNumber?: string;
47+
ropeInfo?: Record<string, string>;
48+
} = {};
4449

4550
constructor(options: IWorldOptions) {
4651
super(options);

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"allowJs": true /* Allow javascript files to be compiled. */,
3838
/* Module Resolution Options */
3939
"moduleResolution": "bundler" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
40-
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
40+
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
4141
"paths": {
4242
"@/*": ["./src/*"]
4343
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */

0 commit comments

Comments
 (0)