Interesting , I ran this website : * https://logistic.rabbitfly.org/rate-calculator on my created “AI Agentic pipeline for Playwright” that writes , heals , adds and even fixes the own framework code" and below are the defects it found on its own, i didnot even see the application.
Defects
Tests written by Agentic pipeline
import { expect, test } from '@fixtures/test.js';
/\*\*
\* Generated for work item 25 ("Rate calculator: verify pricing, volumetric
\* weight, surcharges and validation").
\*
\* Coverage ruling (test_artifacts/25/coverage.md) found all ten acceptance
\* criteria FRAMEWORK_GAP because every locator the journey needs
\* (\`rateCalculator.\*\`) sits inside \`iframe\[title="Shipment tools"\]\` and
\* \`find()\` could not resolve into an iframe's document at all. That gap has
\* since been closed additively in \`find()\`/the locator model (see the header
\* of src/apps/rfl-co-ltd-logistics/locators.ts) and proved with
\* \`APP=all npm run gates\`. Every \`rateCalculator.\*\` locator now names
\* \`frame: 'page.iframe'\` and resolves through the normal AppPage verbs, so
\* all ten criteria are generated here for real.
\*
\* Per the requirement's own instruction: "any calculated total that differs
\* from the value derived from the published rate card and volumetric formula
\* is a defect and must be reported... do not adjust an assertion to make a
\* failing calculation pass." Every assertion below asserts the value the
\* requirement states, unweakened.
\*/
const parseVnd = (text: string): number => {
const digits = text.replace(/\[^\\d\]/g, '');
return Number(digits);
};
test.describe('RFL CO., LTD Logistics - rate calculator', () => {
// Acceptance criterion 1: "Default parcel prices correctly... Calculate
// rate must show a total of 15,000 VND."
test('default parcel (1kg, 20x15x10cm, Intra-city, Standard) totals 15,000 VND', async ({ app }) => {
await app.goto('/rate-calculator');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
await app.expectText('rateCalculator.totalPrice', '15,000 VND');
});
// Acceptance criterion 2: "Volumetric weight is used when it is greater...
// the chargeable weight is 2.0 kg and the total must be 25,000 VND."
test('volumetric weight 2.0 kg (50x20x10cm) on Intra-city totals 25,000 VND', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '50');
await app.fill('rateCalculator.widthInput', '20');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'Intra-city');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
await app.expectText('rateCalculator.chargeableWeightResult', '2.0 kg');
await app.expectText('rateCalculator.totalPrice', '25,000 VND');
});
// Acceptance criterion 3: "Domestic route prices from the Domestic row...
// must total 46,000 VND."
test('same parcel as criterion 2 on Domestic route totals 46,000 VND', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '50');
await app.fill('rateCalculator.widthInput', '20');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'Domestic');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
await app.expectText('rateCalculator.totalPrice', '46,000 VND');
});
// Acceptance criterion 4: "International route prices from the
// International row... must total 240,000 VND."
test('same parcel as criterion 2 on International route totals 240,000 VND', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '50');
await app.fill('rateCalculator.widthInput', '20');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'International');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
await app.expectText('rateCalculator.totalPrice', '240,000 VND');
});
// Acceptance criterion 5: "Express costs more than Standard. For an
// identical parcel, the total returned with Service level Express must be
// strictly greater than the total returned with Service level Standard."
test('Express service totals strictly more than Standard for an identical parcel', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '20');
await app.fill('rateCalculator.widthInput', '15');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'Intra-city');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const standardTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
await app.selectOption('rateCalculator.serviceSelect', 'Express');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const expressTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
expect(expressTotal).toBeGreaterThan(standardTotal);
});
// Acceptance criterion 6: "Insurance increases the total. For an identical
// parcel, the total with Add shipment insurance ticked must be strictly
// greater than the total with it unticked."
test('insurance ticked totals strictly more than the same parcel with insurance off', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '20');
await app.fill('rateCalculator.widthInput', '15');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'Intra-city');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const uninsuredTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
await app.check('rateCalculator.insuranceCheckbox');
await app.fill('rateCalculator.declaredValueInput', '1000000');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const insuredTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
expect(insuredTotal).toBeGreaterThan(uninsuredTotal);
});
// Acceptance criterion 7: "A COD amount increases the total. For an
// identical parcel, a COD amount greater than zero must produce a total
// strictly greater than the same parcel with COD 0."
test('a positive COD amount totals strictly more than the same parcel with COD 0', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '1');
await app.fill('rateCalculator.lengthInput', '20');
await app.fill('rateCalculator.widthInput', '15');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'Intra-city');
await app.selectOption('rateCalculator.serviceSelect', 'Standard');
await app.fill('rateCalculator.codInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const noCodTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
await app.fill('rateCalculator.codInput', '500000');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
const withCodTotal = parseVnd(await app.textOf('rateCalculator.totalPrice'));
expect(withCodTotal).toBeGreaterThan(noCodTotal);
});
// Acceptance criterion 8: "Zero or negative weight is rejected. Entering
// an actual weight of 0, and separately -1, must not produce a price. The
// calculator must show a visible validation message instead."
test('a weight of 0 is rejected with a visible validation message and no price', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '0');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.weightError');
await app.expectHidden('rateCalculator.quoteResult');
});
test('a weight of -1 is rejected with a visible validation message and no price', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '-1');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.weightError');
await app.expectHidden('rateCalculator.quoteResult');
});
// Acceptance criterion 9: "Non-numeric weight is rejected. Entering the
// text \\"abc\\" as the actual weight must not produce a price. The
// calculator must show a visible validation message instead."
test('a non-numeric weight ("abc") is rejected with a visible validation message and no price', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', 'abc');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.weightError');
await app.expectHidden('rateCalculator.quoteResult');
});
// Acceptance criterion 10: "Clear form resets the inputs. After changing
// several fields and clicking Clear form, the inputs must return to their
// defaults and no stale price may remain displayed."
test('Clear form resets changed fields and clears any stale quote', async ({ app }) => {
await app.goto('/rate-calculator');
await app.fill('rateCalculator.weightInput', '5');
await app.fill('rateCalculator.lengthInput', '50');
await app.fill('rateCalculator.widthInput', '20');
await app.fill('rateCalculator.heightInput', '10');
await app.selectOption('rateCalculator.routeSelect', 'International');
await app.selectOption('rateCalculator.serviceSelect', 'Express');
await app.fill('rateCalculator.codInput', '500000');
await app.click('rateCalculator.calculateButton');
await app.expectVisible('rateCalculator.quoteResult');
await app.click('rateCalculator.clearButton');
// Per the locator file's clearButton intent: weight/length/width/height
// become blank (not restored to their original load defaults), COD
// resets to "0", Route reselects "Intra-city", Service level reselects
// "Standard", and the rate card reappears in place of any stale quote.
await app.expectValue('rateCalculator.weightInput', '');
await app.expectValue('rateCalculator.lengthInput', '');
await app.expectValue('rateCalculator.widthInput', '');
await app.expectValue('rateCalculator.heightInput', '');
await app.expectValue('rateCalculator.codInput', '0');
// The <select> options carry internal value codes distinct from their
// visible labels ("Intra-city" -> "noi_thanh", "Standard" -> "tieu_chuan");
// \`expectValue\` asserts the underlying HTML value, so it must match the
// code, not the label shown in the UI.
await app.expectValue('rateCalculator.routeSelect', 'noi_thanh');
await app.expectValue('rateCalculator.serviceSelect', 'tieu_chuan');
await app.expectVisible('rateCalculator.rateCard');
await app.expectHidden('rateCalculator.quoteResult');
});
});
Smoke tests written by AI Agentic pipeline
import { test } from '@fixtures/test.js';
/\*\*
\* Smoke test for the rfl-co-ltd-logistics app profile, run with APP=rfl-co-ltd-logistics.
\*
\* Proves the wiring: the base URL resolves, the app requires no authentication,
\* the rate calculator's iframe is present, and - now that \`find()\` supports a
\* locator naming \`frame\` (see the header of
\* src/apps/rfl-co-ltd-logistics/locators.ts) - a field inside that iframe can
\* actually be resolved through \`AppPage\`, not just the frame boundary itself.
\* This is the proof required before any criterion test for work item 25 can be
\* generated: the shared-machinery change is exercised against a real
\* application, not just compiled.
\*/
test.describe('RFL CO., LTD Logistics', () => {
test('the rate calculator page loads with its tool frame present @smoke', async ({ app }) => {
await app.goto('/rate-calculator');
await app.expectVisible('page.iframe');
});
test('a field inside the iframe resolves and is enabled through find() @smoke', async ({ app }) => {
await app.goto('/rate-calculator');
await app.expectVisible('rateCalculator.weightInput');
await app.expectEnabled('rateCalculator.weightInput');
});
});
Tests generated , passed and failed
It was fun , let me know if you want to see how i achieved this with 6 specialised agents