diff --git a/features/login.feature b/features/login.feature index fb9f1fa..ce58bfd 100644 --- a/features/login.feature +++ b/features/login.feature @@ -5,8 +5,10 @@ Feature: Login Feature Scenario: Validate the login page title # TODO: Fix this failing scenario - Then I should see the title "Labs Swag" + # Solution: The actual title of the page is 'Swag Labs' not 'Labs Swag' + Then I should see the title "Swag Labs" Scenario: Validate login error message Then I will login as 'locked_out_user' - # TODO: Add a step to validate the error message received \ No newline at end of file + # TODO: Add a step to validate the error message received + Then I should see the error message "Epic sadface: Sorry, this user has been locked out." \ No newline at end of file diff --git a/features/product.feature b/features/product.feature index 8a7ceab..7a86b47 100644 --- a/features/product.feature +++ b/features/product.feature @@ -5,9 +5,13 @@ Feature: Product Feature # Create a datatable to validate the Price (high to low) and Price (low to high) sort options (top-right) using a Scenario Outline Scenario Outline: Validate product sort by price - Then I will login as 'standard_user' + Then I will login as 'standard_user' # TODO: Sort the items by + Then I will sort the items by "" # TODO: Validate all 6 items are sorted correctly by price - Examples: - # TODO: extend the datatable to paramterize this test - | sort | \ No newline at end of file + Then I will validate all 6 items are sorted correctly by price "" + Examples: + # TODO: extend the datatable to paramterize this test + | sort | + | Price (low to high) | + | Price (high to low) | \ No newline at end of file diff --git a/features/purchase.feature b/features/purchase.feature index 2863478..278999b 100644 --- a/features/purchase.feature +++ b/features/purchase.feature @@ -4,11 +4,17 @@ Feature: Purchase Feature Given I open the "https://www.saucedemo.com/" page Scenario: Validate successful purchase text - Then I will login as 'standard_user' - Then I will add the backpack to the cart + Then I will login as 'standard_user' + Then I will add the backpack to the cart # TODO: Select the cart (top-right) + When I will navigate to the cart # TODO: Select Checkout + And I will select checkout # TODO: Fill in the First Name, Last Name, and Zip/Postal Code + Then I will fill First Name "Jerome", Last Name "Nithish", and Postal code "600091" # TODO: Select Continue + When I will select continue # TODO: Select Finish - # TODO: Validate the text 'Thank you for your order!' \ No newline at end of file + And I will select finish + # TODO: Validate the text 'Thank you for your order!' + Then I should see the success message "Thank you for your order!" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b90d7c6..9b41cbe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "Playwright-Project", + "name": "Playwright-Cucumber-Exercise", "lockfileVersion": 3, "requires": true, "packages": { "": { "devDependencies": { - "@cucumber/cucumber": "^10.0.1", + "@cucumber/cucumber": "^10.9.0", "@cucumber/pretty-formatter": "^1.0.0", - "@playwright/test": "^1.40.1", + "@playwright/test": "^1.58.2", "@types/node": "^20.10.3", "cucumber-html-reporter": "^7.1.1", "ts-node": "^10.9.1", @@ -179,26 +179,28 @@ } }, "node_modules/@cucumber/ci-environment": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-9.2.0.tgz", - "integrity": "sha512-jLzRtVwdtNt+uAmTwvXwW9iGYLEOJFpDSmnx/dgoMGKXUWRx1UHT86Q696CLdgXO8kyTwsgJY0c6n5SW9VitAA==", - "dev": true + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-10.0.1.tgz", + "integrity": "sha512-/+ooDMPtKSmvcPMDYnMZt4LuoipfFfHaYspStI4shqw8FyKcfQAmekz6G+QKWjQQrvM+7Hkljwx58MEwPCwwzg==", + "dev": true, + "license": "MIT" }, "node_modules/@cucumber/cucumber": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-10.0.1.tgz", - "integrity": "sha512-g7W7SQnNMSNnMRQVGubjefCxdgNFyq4P3qxT2Ve7Xhh8ZLoNkoRDcWsyfKQVWnxNfgW3aGJmxbucWRoTi+ZUqg==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-10.9.0.tgz", + "integrity": "sha512-7XHJ6nmr9IkIag0nv6or82HfelbSInrEe3H4aT6dMHyTehwFLUifG6eQQ+uE4LZIOXAnzLPH37YmqygEO67vCA==", "dev": true, + "license": "MIT", "dependencies": { - "@cucumber/ci-environment": "9.2.0", - "@cucumber/cucumber-expressions": "16.1.2", - "@cucumber/gherkin": "26.2.0", + "@cucumber/ci-environment": "10.0.1", + "@cucumber/cucumber-expressions": "17.1.0", + "@cucumber/gherkin": "28.0.0", "@cucumber/gherkin-streams": "5.0.1", - "@cucumber/gherkin-utils": "8.0.2", - "@cucumber/html-formatter": "20.4.0", + "@cucumber/gherkin-utils": "9.0.0", + "@cucumber/html-formatter": "21.6.0", "@cucumber/message-streams": "4.0.1", - "@cucumber/messages": "22.0.0", - "@cucumber/tag-expressions": "5.0.1", + "@cucumber/messages": "24.1.0", + "@cucumber/tag-expressions": "6.1.0", "assertion-error-formatter": "^3.0.0", "capital-case": "^1.0.4", "chalk": "^4.1.2", @@ -216,18 +218,19 @@ "lodash.merge": "^4.6.2", "lodash.mergewith": "^4.6.2", "luxon": "3.2.1", + "mime": "^3.0.0", "mkdirp": "^2.1.5", "mz": "^2.7.0", "progress": "^2.0.3", "read-pkg-up": "^7.0.1", "resolve-pkg": "^2.0.0", "semver": "7.5.3", - "string-argv": "^0.3.1", + "string-argv": "0.3.1", "strip-ansi": "6.0.1", "supports-color": "^8.1.1", - "tmp": "^0.2.1", + "tmp": "0.2.3", + "type-fest": "^4.8.3", "util-arity": "^1.1.0", - "verror": "^1.10.0", "xmlbuilder": "^15.1.1", "yaml": "^2.2.2", "yup": "1.2.0" @@ -237,24 +240,96 @@ }, "engines": { "node": "18 || >=20" + }, + "funding": { + "url": "https://opencollective.com/cucumber" } }, "node_modules/@cucumber/cucumber-expressions": { - "version": "16.1.2", - "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-16.1.2.tgz", - "integrity": "sha512-CfHEbxJ5FqBwF6mJyLLz4B353gyHkoi6cCL4J0lfDZ+GorpcWw4n2OUAdxJmP7ZlREANWoTFlp4FhmkLKrCfUA==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-17.1.0.tgz", + "integrity": "sha512-PCv/ppsPynniKPWJr5v566daCVe+pbxQpHGrIu/Ev57cCH9Rv+X0F6lio4Id3Z64TaG7btCRLUGewIgLwmrwOA==", "dev": true, + "license": "MIT", "dependencies": { "regexp-match-indices": "1.0.2" } }, + "node_modules/@cucumber/cucumber/node_modules/@cucumber/gherkin-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-9.0.0.tgz", + "integrity": "sha512-clk4q39uj7pztZuZtyI54V8lRsCUz0Y/p8XRjIeHh7ExeEztpWkp4ca9q1FjUOPfQQ8E7OgqFbqoQQXZ1Bx7fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cucumber/gherkin": "^28.0.0", + "@cucumber/messages": "^24.0.0", + "@teppeis/multimaps": "3.0.0", + "commander": "12.0.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "gherkin-utils": "bin/gherkin-utils" + } + }, + "node_modules/@cucumber/cucumber/node_modules/@cucumber/gherkin-utils/node_modules/commander": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", + "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cucumber/cucumber/node_modules/@cucumber/tag-expressions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-6.1.0.tgz", + "integrity": "sha512-+3DwRumrCJG27AtzCIL37A/X+A/gSfxOPLg8pZaruh5SLumsTmpvilwroVWBT2fPzmno/tGXypeK5a7NHU4RzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cucumber/cucumber/node_modules/@teppeis/multimaps": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@teppeis/multimaps/-/multimaps-3.0.0.tgz", + "integrity": "sha512-ID7fosbc50TbT0MK0EG12O+gAP3W3Aa/Pz4DaTtQtEvlc9Odaqi0de+xuZ7Li2GtK4HzEX7IuRWS/JmZLksR3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@cucumber/cucumber/node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/@cucumber/cucumber/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@cucumber/gherkin": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-26.2.0.tgz", - "integrity": "sha512-iRSiK8YAIHAmLrn/mUfpAx7OXZ7LyNlh1zT89RoziSVCbqSVDxJS6ckEzW8loxs+EEXl0dKPQOXiDmbHV+C/fA==", + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-28.0.0.tgz", + "integrity": "sha512-Ee6zJQq0OmIUPdW0mSnsCsrWA2PZAELNDPICD2pLfs0Oz7RAPgj80UsD2UCtqyAhw2qAR62aqlktKUlai5zl/A==", "dev": true, + "license": "MIT", "dependencies": { - "@cucumber/messages": ">=19.1.4 <=22" + "@cucumber/messages": ">=19.1.4 <=24" } }, "node_modules/@cucumber/gherkin-streams": { @@ -337,10 +412,11 @@ } }, "node_modules/@cucumber/html-formatter": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-20.4.0.tgz", - "integrity": "sha512-TnLSXC5eJd8AXHENo69f5z+SixEVtQIf7Q2dZuTpT/Y8AOkilGpGl1MQR1Vp59JIw+fF3EQSUKdf+DAThCxUNg==", + "version": "21.6.0", + "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-21.6.0.tgz", + "integrity": "sha512-Qw1tdObBJrgXgXwVjKVjB3hFhFPI8WhIFb+ULy8g5lDl5AdnKDiyDXAMvAWRX+pphnRMMNdkPCt6ZXEfWvUuAA==", "dev": true, + "license": "MIT", "peerDependencies": { "@cucumber/messages": ">=18" } @@ -355,15 +431,38 @@ } }, "node_modules/@cucumber/messages": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-22.0.0.tgz", - "integrity": "sha512-EuaUtYte9ilkxcKmfqGF9pJsHRUU0jwie5ukuZ/1NPTuHS1LxHPsGEODK17RPRbZHOFhqybNzG2rHAwThxEymg==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-24.1.0.tgz", + "integrity": "sha512-hxVHiBurORcobhVk80I9+JkaKaNXkW6YwGOEFIh/2aO+apAN+5XJgUUWjng9NwqaQrW1sCFuawLB1AuzmBaNdQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/uuid": "9.0.1", + "@types/uuid": "9.0.8", "class-transformer": "0.5.1", - "reflect-metadata": "0.1.13", - "uuid": "9.0.0" + "reflect-metadata": "0.2.1", + "uuid": "9.0.1" + } + }, + "node_modules/@cucumber/messages/node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==", + "deprecated": "This version has a critical bug in fallback handling. Please upgrade to reflect-metadata@0.2.2 or newer.", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@cucumber/messages/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/@cucumber/pretty-formatter": { @@ -491,18 +590,19 @@ } }, "node_modules/@playwright/test": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", - "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright": "1.40.1" + "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@teppeis/multimaps": { @@ -560,10 +660,11 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", - "dev": true + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" }, "node_modules/acorn": { "version": "8.11.2", @@ -1308,6 +1409,7 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1652,6 +1754,19 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -1900,33 +2015,35 @@ } }, "node_modules/playwright": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", - "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.40.1" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", - "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/progress": { @@ -2062,63 +2179,6 @@ "node": ">=8" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/seed-random": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", @@ -2378,15 +2438,13 @@ "dev": true }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/toposort": { diff --git a/package.json b/package.json index ed38f6f..edc367a 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "report": "node generate-report.js" }, "devDependencies": { - "@cucumber/cucumber": "^10.0.1", + "@cucumber/cucumber": "^10.9.0", "@cucumber/pretty-formatter": "^1.0.0", - "@playwright/test": "^1.40.1", + "@playwright/test": "^1.58.2", "@types/node": "^20.10.3", "cucumber-html-reporter": "^7.1.1", "ts-node": "^10.9.1", diff --git a/pages/cart.page.ts b/pages/cart.page.ts new file mode 100644 index 0000000..2dd66b8 --- /dev/null +++ b/pages/cart.page.ts @@ -0,0 +1,37 @@ +import { expect, Page } from "@playwright/test"; + +export class Cart { + private readonly page: Page + private readonly firstNameField: string = '#first-name'; + private readonly lastNameField: string = '#last-name'; + private readonly postalCodeField: string = '#postal-code'; + private readonly thankYouMessage: string = '.complete-header'; + + constructor(page: Page) { + this.page = page; + } + + public async clickOnCheckout() { + await this.page.getByRole('button', { name: 'Checkout' }).click(); + } + + public async fillPersonalDetails(firstName: string, lastName: string, postalCode: string) { + await this.page.locator(this.firstNameField).fill(firstName); + await this.page.locator(this.lastNameField).fill(lastName); + await this.page.locator(this.postalCodeField).fill(postalCode); + await this.page.screenshot({path: './screenshots/personal_details_checkout.jpg'}) + } + + public async clickOnContinue() { + await this.page.getByRole('button', { name: 'Continue' }).click(); + } + + public async clickOnFinish() { + await this.page.getByRole('button', { name: 'Finish' }).click(); + } + + public async validateThankYouMessage(exp_message: string) { + await expect(this.page.locator(this.thankYouMessage)).toHaveText(exp_message); + await this.page.screenshot({path: './screenshots/thankYou_Message.jpg'}) + } +} \ No newline at end of file diff --git a/pages/login.page.ts b/pages/login.page.ts index 5a01614..82232e5 100644 --- a/pages/login.page.ts +++ b/pages/login.page.ts @@ -1,4 +1,4 @@ -import { Page } from "@playwright/test" +import { expect, Page } from "@playwright/test" export class Login { private readonly page: Page @@ -6,6 +6,7 @@ export class Login { private readonly passwordField: string = 'input[id="password"]' private readonly userNameField: string = 'input[id="user-name"]' private readonly loginButton: string = 'input[id="login-button"]' + private readonly errorMsg: string = '[data-test="error"]' constructor(page: Page) { this.page = page; @@ -21,6 +22,13 @@ export class Login { public async loginAsUser(userName: string) { await this.page.locator(this.userNameField).fill(userName) await this.page.locator(this.passwordField).fill(this.password) + await this.page.screenshot({path: './screenshots/login_page.jpg'}) await this.page.locator(this.loginButton).click() } + + public async validateErrorMsg(exp_errorMsg: string){ + const act_errorMsg = await this.page.locator(this.errorMsg).textContent(); + expect(act_errorMsg).toBe(exp_errorMsg); + await this.page.screenshot({path: './screenshots/error_message_in_login_page.jpg'}) + } } \ No newline at end of file diff --git a/pages/product.page.ts b/pages/product.page.ts index 14bedb1..bc13958 100644 --- a/pages/product.page.ts +++ b/pages/product.page.ts @@ -1,14 +1,40 @@ -import { Page } from "@playwright/test" +import { expect, Page } from "@playwright/test" +import exp from "constants" export class Product { private readonly page: Page private readonly addToCart: string = 'button[id="add-to-cart-sauce-labs-backpack"]' + private readonly cartButton: string = 'a.shopping_cart_link' + private readonly sortDropdown: string = 'select.product_sort_container' + private readonly itemPrices: string = '.inventory_item_price' constructor(page: Page) { this.page = page; } public async addBackPackToCart() { - await this.page.locator(this.addToCart).click() + await this.page.locator(this.addToCart).click(); + } + + public async clickOnCart() { + await this.page.locator(this.cartButton).click(); + } + + public async sortItemsByPrice(sortOption: string) { + await this.page.locator(this.sortDropdown).selectOption(sortOption); + } + + public async validateItemsAreSortedByPrice(sortOption: string) { + const itemPrices = await this.page.locator(this.itemPrices).allTextContents(); + const priceValues = itemPrices.map(itemPrices => parseFloat(itemPrices.replace('$', ''))); + const sortedPrices = [...priceValues].sort((a, b) => a - b); + if (sortOption === 'Price (low to high)') { + expect(priceValues).toEqual(sortedPrices); + await this.page.screenshot({path: './screenshots/Price (low to high).jpg', fullPage: true}); + } + else if (sortOption === 'Price (high to low)') { + expect(priceValues).toEqual([...sortedPrices].reverse()); + await this.page.screenshot({path: './screenshots/Price (high to low).jpg', fullPage: true}); + } } } \ No newline at end of file diff --git a/screenshots/Price (high to low).jpg b/screenshots/Price (high to low).jpg new file mode 100644 index 0000000..f084389 Binary files /dev/null and b/screenshots/Price (high to low).jpg differ diff --git a/screenshots/Price (low to high).jpg b/screenshots/Price (low to high).jpg new file mode 100644 index 0000000..2c37c44 Binary files /dev/null and b/screenshots/Price (low to high).jpg differ diff --git a/screenshots/error_login.jpg b/screenshots/error_login.jpg new file mode 100644 index 0000000..082d822 Binary files /dev/null and b/screenshots/error_login.jpg differ diff --git a/screenshots/error_message_in_login_page.jpg b/screenshots/error_message_in_login_page.jpg new file mode 100644 index 0000000..082d822 Binary files /dev/null and b/screenshots/error_message_in_login_page.jpg differ diff --git a/screenshots/login.jpg b/screenshots/login.jpg new file mode 100644 index 0000000..3a3df24 Binary files /dev/null and b/screenshots/login.jpg differ diff --git a/screenshots/login_page.jpg b/screenshots/login_page.jpg new file mode 100644 index 0000000..3a3df24 Binary files /dev/null and b/screenshots/login_page.jpg differ diff --git a/screenshots/personal_details.jpg b/screenshots/personal_details.jpg new file mode 100644 index 0000000..79642a3 Binary files /dev/null and b/screenshots/personal_details.jpg differ diff --git a/screenshots/personal_details_checkout.jpg b/screenshots/personal_details_checkout.jpg new file mode 100644 index 0000000..79642a3 Binary files /dev/null and b/screenshots/personal_details_checkout.jpg differ diff --git a/screenshots/thankYouMessage.jpg b/screenshots/thankYouMessage.jpg new file mode 100644 index 0000000..09115fd Binary files /dev/null and b/screenshots/thankYouMessage.jpg differ diff --git a/screenshots/thankYou_Message.jpg b/screenshots/thankYou_Message.jpg new file mode 100644 index 0000000..09115fd Binary files /dev/null and b/screenshots/thankYou_Message.jpg differ diff --git a/steps/cart.steps.ts b/steps/cart.steps.ts new file mode 100644 index 0000000..377f6a0 --- /dev/null +++ b/steps/cart.steps.ts @@ -0,0 +1,23 @@ +import { Then, When } from '@cucumber/cucumber'; +import { getPage } from '../playwrightUtilities'; +import { Cart } from '../pages/cart.page'; + +When('I will select checkout', async () => { + await new Cart(getPage()).clickOnCheckout(); +}) + +Then('I will fill First Name {string}, Last Name {string}, and Postal code {string}', async (firstName, lastName, postalCode) => { + await new Cart(getPage()).fillPersonalDetails(firstName, lastName, postalCode); +}) + +When('I will select continue', async () => { + await new Cart(getPage()).clickOnContinue(); +}) + +When('I will select finish', async () => { + await new Cart(getPage()).clickOnFinish(); +}) + +Then('I should see the success message {string}', async (exp_message) => { + await new Cart(getPage()).validateThankYouMessage(exp_message); +}) \ No newline at end of file diff --git a/steps/login.steps.ts b/steps/login.steps.ts index c2aa0d8..a6ad030 100644 --- a/steps/login.steps.ts +++ b/steps/login.steps.ts @@ -8,4 +8,8 @@ Then('I should see the title {string}', async (expectedTitle) => { Then('I will login as {string}', async (userName) => { await new Login(getPage()).loginAsUser(userName); -}); \ No newline at end of file +}); + +Then('I should see the error message {string}', async (errorMsg) => { + await new Login(getPage()).validateErrorMsg(errorMsg); +}) \ No newline at end of file diff --git a/steps/product.steps.ts b/steps/product.steps.ts index bb52fb9..e726fab 100644 --- a/steps/product.steps.ts +++ b/steps/product.steps.ts @@ -1,7 +1,19 @@ -import { Then } from '@cucumber/cucumber'; +import { Then, When } from '@cucumber/cucumber'; import { getPage } from '../playwrightUtilities'; import { Product } from '../pages/product.page'; Then('I will add the backpack to the cart', async () => { await new Product(getPage()).addBackPackToCart(); +}); + +When('I will navigate to the cart', async () => { + await new Product(getPage()).clickOnCart(); +}); + +Then('I will sort the items by {string}', async (sortOption) => { + await new Product(getPage()).sortItemsByPrice(sortOption); +}); + +Then('I will validate all 6 items are sorted correctly by price {string}', async(sortOption) => { + await new Product(getPage()).validateItemsAreSortedByPrice(sortOption); }); \ No newline at end of file