Skip to content

Commit b45750f

Browse files
refactor and all test pass
1 parent 1cfcaa4 commit b45750f

9 files changed

Lines changed: 228 additions & 138 deletions

File tree

cypress.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dotenv.config()
66

77
module.exports = defineConfig({
88
e2e: {
9+
defaultCommandTimeout: 60000,
910
setupNodeEvents(on, config) {
1011
allureWriter(on, config)
1112
config.env.API_KEY = process.env.API_KEY

cypress/e2e/uploadFreeText.spec.cy.js

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import UploadTextOrUrl from '../modules/UploadTextOrUrl'
2+
3+
const uploadTextOrUrl = new UploadTextOrUrl()
4+
5+
describe('UploadFreeText API tests - individual - valid inputs', () => {
6+
const validInputs = ['input1', 'input2', 'input3', 'input4']
7+
8+
validInputs.forEach(inputKey => {
9+
it(`should upload text and validate success response with matched items ${inputKey}`, () => {
10+
const meta = uploadTextOrUrl.inputMeta[inputKey]
11+
const { endpointKey, statusKey } = uploadTextOrUrl.getResolvedApiAndStatus(meta, 0)
12+
const expectedProductKey = meta.expectedProductKey
13+
const inputText = uploadTextOrUrl.input[inputKey]
14+
15+
return uploadTextOrUrl.uploadAndValidateMatchedProducts(
16+
inputText,
17+
expectedProductKey,
18+
statusKey,
19+
endpointKey
20+
)
21+
})
22+
})
23+
})
24+
25+
describe('UploadFreeText API tests - individual - invalid inputs', () => {
26+
it(`should upload text and validate failure response with invalid input5`, () => {
27+
const meta = uploadTextOrUrl.inputMeta.input5
28+
const { endpointKey, statusKey } = uploadTextOrUrl.getResolvedApiAndStatus(meta, 0)
29+
const inputText = uploadTextOrUrl.input.input5
30+
31+
return uploadTextOrUrl.uploadAndValidateStatus(
32+
inputText,
33+
statusKey,
34+
false,
35+
endpointKey
36+
)
37+
})
38+
})
39+
40+
describe('UploadFreeText API tests - only valid combinations', () => {
41+
const validCombinations = uploadTextOrUrl.getValidInputApiCombinations()
42+
43+
validCombinations.forEach(([inputKey, apiKey]) => {
44+
it(`should validate ${inputKey} with ${apiKey}`, () => {
45+
return uploadTextOrUrl.validateInputKey(inputKey, apiKey)
46+
})
47+
})
48+
})

cypress/fixtures/endpoint.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"api1": "/rfq/upload-free-text",
3+
"api2": "/rfq/upload-url-html",
4+
"api3": "/rfq/upload-neki-test"
5+
}

cypress/fixtures/input.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"input1": "Choice 24\" x 18\" x 1/2\" Green Polyethylene Cutting Board",
3+
"input2": "Choice 4 Qt. White Square Polypropylene Food Storage Container and Green Lid - 6/Pack",
4+
"input3": "https://www.webstaurantstore.com/choice-24-x-18-x-1-2-green-polyethylene-cutting-board/40724185GN.html",
5+
"input4": "https://www.webstaurantstore.com/choice-4-qt-white-square-polypropylene-food-storage-container-and-green-lid-pack/176SQWH4KT6.html",
6+
"input5": ""
7+
}

cypress/fixtures/statusCodes.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@
44
"apiStatus": "Succeeded",
55
"isSuccess": true
66
},
7-
"SUCCESS2": {
8-
"httpStatus": 200,
9-
"apiStatus": "Succeeded",
10-
"isSuccess": true
11-
},
127
"CREATED": {
138
"httpStatus": 201,
149
"apiStatus": "Created",

cypress/modules/UploadFreeText.js

Lines changed: 0 additions & 97 deletions
This file was deleted.

cypress/modules/UploadTextOrUrl.js

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import statusCodes from '../fixtures/statusCodes.json'
2+
import endpoint from '../fixtures/endpoint.json'
3+
import input from '../fixtures/input.json'
4+
5+
export default class UploadTextOrUrl {
6+
constructor() {
7+
this.endpoint = endpoint || {}
8+
this.input = input || {}
9+
this.statusCodes = statusCodes || {}
10+
11+
this.expectedProductTerms = {
12+
cuttingBoard: ['Cutting Board'],
13+
storageContainer: ['4 Qt Container', 'Food Storage Container']
14+
}
15+
16+
this.inputMeta = null
17+
this.initInputMeta()
18+
}
19+
20+
initInputMeta() {
21+
this.inputMeta = {
22+
input1: {
23+
apis: [
24+
{ endpointKey: 'api1', statusKey: 'SUCCESS' },
25+
{ endpointKey: 'api3', statusKey: 'NOT_FOUND' }
26+
],
27+
expectedProductKey: 'cuttingBoard',
28+
},
29+
input2: {
30+
apis: [
31+
{ endpointKey: 'api1', statusKey: 'SUCCESS' },
32+
{ endpointKey: 'api3', statusKey: 'NOT_FOUND' }
33+
],
34+
expectedProductKey: 'storageContainer',
35+
},
36+
input3: {
37+
apis: [
38+
{ endpointKey: 'api2', statusKey: 'SUCCESS' },
39+
{ endpointKey: 'api3', statusKey: 'NOT_FOUND' }
40+
],
41+
expectedProductKey: 'cuttingBoard',
42+
},
43+
input4: {
44+
apis: [
45+
{ endpointKey: 'api2', statusKey: 'SUCCESS' },
46+
{ endpointKey: 'api3', statusKey: 'NOT_FOUND' }
47+
],
48+
expectedProductKey: 'storageContainer',
49+
},
50+
input5: {
51+
apis: [
52+
{ endpointKey: 'api1', statusKey: 'BAD_REQUEST' },
53+
{ endpointKey: 'api2', statusKey: 'BAD_REQUEST' },
54+
{ endpointKey: 'api3', statusKey: 'NOT_FOUND' }
55+
],
56+
expectedProductKey: null,
57+
},
58+
}
59+
}
60+
61+
upload(textUpload, failOnStatusCode = true, endpointKey) {
62+
const url = this.endpoint[endpointKey]
63+
if (!url) throw new Error(`Unknown endpoint key "${endpointKey}"`)
64+
if (textUpload === undefined || textUpload === null) {
65+
throw new Error(`Missing required text for endpoint "${endpointKey}"`)
66+
}
67+
68+
const field = endpointKey === 'api2' ? 'url' : 'text'
69+
const requestBody = {
70+
[field]: textUpload,
71+
topK: 3,
72+
threshold: 0.8,
73+
enablePrivateLabelRanking: false,
74+
enableStockProductRanking: false,
75+
enableVendorRanking: false
76+
}
77+
78+
return cy.postApi(url, requestBody, { failOnStatusCode })
79+
}
80+
81+
uploadAndValidateStatus(text, statusKey, failOnStatusCode = true, endpointKey) {
82+
const expected = this.statusCodes[statusKey]
83+
if (!expected) throw new Error(`Unknown statusKey "${statusKey}" in statusCodes`)
84+
85+
return this.upload(text, failOnStatusCode, endpointKey).then(response => {
86+
expect(response.status).to.eq(expected.httpStatus)
87+
88+
const body = response.body
89+
90+
if (!body || Object.keys(body).length === 0) {
91+
cy.log('Response body is empty – skipping body field assertions')
92+
} else if (body.error_code !== undefined) {
93+
expect(body.error_code).to.eq(expected.apiStatus)
94+
expect(body.IsSuccess).to.eq(expected.isSuccess)
95+
} else if (body.status !== undefined && body.isSuccess !== undefined) {
96+
expect(body.status).to.eq(expected.apiStatus)
97+
expect(body.isSuccess).to.eq(expected.isSuccess)
98+
} else {
99+
cy.log('Unexpected response body structure:', JSON.stringify(body, null, 2))
100+
}
101+
return cy.wrap(response)
102+
})
103+
}
104+
105+
uploadAndValidateMatchedProducts(text, expectedProductKey, statusKey, endpointKey) {
106+
const expectedTerms = this.expectedProductTerms[expectedProductKey] || []
107+
108+
return this.uploadAndValidateStatus(text, statusKey, true, endpointKey).then(response => {
109+
const matchedItems = response.body.result?.matchedItems || []
110+
expect(matchedItems).to.be.an('array').that.is.not.empty
111+
112+
const foundTerm = matchedItems.some(item =>
113+
expectedTerms.some(term =>
114+
item.productName.toLowerCase().includes(term.toLowerCase())
115+
)
116+
)
117+
expect(foundTerm, 'Expected product terms not found in matched items').to.be.true
118+
119+
return response
120+
})
121+
}
122+
123+
validateInputKey(inputKey, apiKey) {
124+
const endpoint = this.endpoint[apiKey]
125+
if (!endpoint) throw new Error(`Unknown endpoint key "${apiKey}"`)
126+
127+
const textUpload = this.input[inputKey]
128+
if (textUpload === undefined) throw new Error(`Unknown input key "${inputKey}"`)
129+
130+
const apiMeta = this.inputMeta[inputKey]?.apis.find(api => api.endpointKey === apiKey)
131+
const expectedStatusCode = apiMeta?.statusKey === 'SUCCESS' ? 200 : 400
132+
const failOnStatusCode = expectedStatusCode === 200
133+
134+
return this.uploadAndValidateStatus(textUpload, apiMeta.statusKey, failOnStatusCode, apiKey)
135+
}
136+
137+
getResolvedApiAndStatus(inputMeta, apiIndex = 0) {
138+
const api = inputMeta.apis[apiIndex]
139+
return {
140+
endpointKey: api.endpointKey,
141+
statusKey: api.statusKey,
142+
}
143+
}
144+
145+
getValidInputApiCombinations() {
146+
if (!this.inputMeta) this.initInputMeta()
147+
148+
const combinations = []
149+
150+
for (const inputKey in this.inputMeta) {
151+
const apis = this.inputMeta[inputKey].apis || []
152+
apis.forEach(api => {
153+
if (
154+
api.statusKey === 'SUCCESS' ||
155+
api.statusKey === 'NOT_FOUND' ||
156+
api.statusKey === 'BAD_REQUEST'
157+
) {
158+
combinations.push([inputKey, api.endpointKey])
159+
}
160+
})
161+
}
162+
163+
return combinations
164+
}
165+
166+
}

cypress/support/commands.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ Cypress.Commands.add('postApi', (endpoint, body, options = {}) => {
3434
Authorization: Cypress.env('API_KEY'),
3535
'Content-Type': 'application/json',
3636
accept: 'text/plain',
37-
}
37+
},
3838
})
3939
})

0 commit comments

Comments
 (0)