Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • osl/code/org.etsi.osl.tmf.web
1 result
Show changes
Commits on Source (8)
...@@ -40,6 +40,7 @@ npm-debug.log ...@@ -40,6 +40,7 @@ npm-debug.log
yarn-error.log yarn-error.log
testem.log testem.log
/typings /typings
.env
# System Files # System Files
.DS_Store .DS_Store
......
import { defineConfig } from "cypress";
import * as dotenv from "dotenv";
dotenv.config();
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
require("ts-node").register({
project: "tsconfig.json",
});
return config;
},
//baseUrl: "http://orgosletsitmfweb:4200",
baseUrl: process.env.CYPRESS_BASE_URL,
pageLoadTimeout: 16000,
viewportWidth: 1500,
viewportHeight: 900,
env: {
username: process.env.CYPRESS_username,
password: process.env.CYPRESS_password
}
},
});
describe('user authentication', () => {
beforeEach(() => {
cy.visit(window.location.origin);
})
//edit profile bug
it('should block unauthenticated user from entering a protected route', () => {
cy.fixture("routes.json").then((data) => {
cy.log(data.routes);
// cy.wrap(data.routes).as("protectedRoutes");
for(let route of data.routes) {
cy.intercept(route);
cy.log(route);
cy.visit(route);
cy.location("pathname").should("equal", "/");
}
});
});
it('should display login errors when nothing is typed', () => {
cy.get(':nth-child(1) > .nav-link').click();
cy.location("pathname").should("equal", '/services');
cy.get('.btn').should("contain", "Sign In").click();
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
cy.get('#kc-login').click();
cy.get('#input-error').should('be.visible').and('contain','Invalid username or password.');
cy.get('[aria-invalid="true"]').should('have.length', 2); //the 2 input fields should have selector aria-invalid = 'true'
});
});
it('should display login errors when credentials are wrong', () => {
cy.get(':nth-child(1) > .nav-link').click();
cy.location("pathname").should("equal", '/services');
cy.get('.btn').should("contain", "Sign In").click();
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
cy.get('#username').type('test').blur();
cy.get('#password').type('test').blur();
cy.get('#kc-login').click();
cy.get('#input-error').should('be.visible').and('contain','Invalid username or password.');
cy.get('[aria-invalid="true"]').should('have.length', 2); //the 2 input fields should have selector aria-invalid = 'true'
});
});
it('should login, logout', () => {
cy.loginPath(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn', '/services');
cy.get('#navbarDropdown2').click();
cy.window().then((win) => {
expect(win.localStorage.getItem('access_token')).to.exist;
})
cy.get(':nth-child(2) > .dropdown > .dropdown-menu > :nth-child(8)').click();
cy.location("pathname").should("equal", "/");
});
it('forget password should work', () => {
cy.get(':nth-child(1) > .nav-link').click();
cy.location("pathname").should("equal", '/services');
cy.get('.btn').should("contain", "Sign In").click();
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
cy.get(':nth-child(2) > span > a').click();
cy.location("pathname").should("equal", "/auth/realms/openslice/login-actions/reset-credentials");
cy.get('#username').should('exist');
});
});
context('register form', () => {
beforeEach(() => {
cy.get(':nth-child(1) > .nav-link').click();
cy.location("pathname").should("equal", '/services');
cy.get('.btn').should("contain", "Sign In").click();
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
cy.get('#kc-registration > span > a').click();
cy.location("pathname").should("equal", "/auth/realms/openslice/login-actions/registration");
});
})
it('register form should not be empty when submitted', () => {
cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => {
cy.get('.pf-c-button').click();
cy.get('#input-error-firstname').should('exist').and('contain', 'Please specify first name.');
cy.get('#input-error-lastname').should('exist').and('contain', 'Please specify last name.');
cy.get('#input-error-email').should('exist').and('contain', 'Please specify email.');
cy.get('#input-error-username').should('exist').and('contain', 'Please specify username.');
cy.get('#input-error-password').should('exist').and('contain', 'Please specify password.');
});
});
it('invalid email', () => {
cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => {
cy.get('#email').type('email');
cy.get('.pf-c-button').click();
cy.get('#input-error-email').should('exist').and('contain','Invalid email address.');
cy.get('#email').type('@example.com');
cy.get('.pf-c-button').click();
cy.get('#input-error-email').should('not.exist');
});
});
it('confirm password field should be the same with password', () => {
cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => {
cy.get('#password').type('123');
cy.get('#password-confirm').type('1234');
cy.get('.pf-c-button').click();
cy.get('#input-error-password-confirm').should('exist').and('contain',"Password confirmation doesn't match.");
cy.get('#password').type('123');
cy.get('#password-confirm').type('123');
cy.get('.pf-c-button').click();
cy.get('#input-error-password-confirm').should('not.exist');
});
});
})
})
\ No newline at end of file
describe('logged user journeys', () => {
beforeEach(() => {
//cy.visit("http://localhost:4200/");
cy.visit(window.location.origin);
});
afterEach(() => {
//log user out after each test
cy.get('#navbarDropdown2').click();
cy.get(':nth-child(2) > .dropdown > .dropdown-menu > :nth-child(8)').click();
cy.location("pathname").should("equal", "/");
});
it('logs in through services', () => {
cy.loginPath(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn', '/services');
//back on services marketplace after login
cy.location("pathname").should("equal", "/services/services_marketplace");
//check every 'Manage Services' dropdown item
cy.get(':nth-child(2) > #navbarDropdown').click();
let i=0;
cy.get('.show .dropdown-item').each(($el) => {
i++;
cy.wrap($el).click(); // Click the link
cy.get(':nth-child(1) > .cdk-column-actions > .btn').first().click();
//does the dialog open?
cy.get('mat-dialog-container').should('exist');
cy.go('back');
cy.get(':nth-child(2) > #navbarDropdown').click();
if(i>1) {
return false;
}
});
//access the service specs dropdown
cy.get('#navbarDropdown1').click();
let j=0;
for(let i=1; i<=2; i++) {
cy.get(`.dropdown-submenu > .dropdown-menu > :nth-child(${i}) `).click();
cy.location("pathname").should("not.equal", "/services/services_marketplace");
cy.go('back');
cy.get(':nth-child(2) > #navbarDropdown').click();
cy.get('#navbarDropdown1').click();
}
//check the rest dropdown items
cy.get(':nth-child(4) > .dropdown-item').click();
cy.get('mat-dialog-container').should('exist');
cy.go('back');
cy.get(':nth-child(2) > #navbarDropdown').click();
//'Manage Entities' dropdown
cy.manageEntities(':nth-child(3) > #navbarDropdown', '.jumbotron-heading > .btn', 2, 2);
});
it('logs in through resources', () => {
cy.loginPath(':nth-child(3) > .container > .row > .order-md-1 > a > .btn', '/resources');
cy.location("pathname").should("equal", "/resources/resource_catalogs");
cy.get('.text-md-right > .btn').click();
cy.get('mat-dialog-container').should('exist');
cy.go('back');
cy.get('#navbarDropdown').click();
cy.get('.show > :nth-child(2) > .dropdown-item').click();
cy.location("pathname").should("equal", "/resources/resource_categories");
cy.get('.text-md-right > .btn').click();
cy.location("pathname").should("equal", "/resources/resource_categories_update");
cy.go('back');
cy.get('#navbarDropdown').click();
cy.get('#navbarDropdown1').click();
for(let i=1; i<=2; i++) {
cy.get(`.dropdown-submenu > .dropdown-menu > :nth-child(${i}) `).click();
cy.location("pathname").should("not.equal", "/resources/resource_categories");
cy.go('back');
cy.get('#navbarDropdown').click();
cy.get('#navbarDropdown1').click();
}
//resource inventory
cy.get(':nth-child(5) > .dropdown-item').click();
cy.location("pathname").should("equal", "/resources/resource_inventory");
cy.get('#navbarDropdown').click();
//resource pools
cy.get(':nth-child(7) > .dropdown-item').click();
cy.location("pathname").should("equal", "/resources/resource_pools");
cy.get('#navbarDropdown').click();
//resource reservations
cy.get(':nth-child(8) > .dropdown-item').click();
cy.location("pathname").should("equal", "/resources/resource_reservations");
});
it('logs in through testing', () => {
cy.loginPath(':nth-child(5) > .container > .row > .order-md-1 > a > .btn', '/testing');
cy.manageEntities(':nth-child(1) > #navbarDropdown', '.text-md-right > .btn', 3, 2);
cy.manageEntities(':nth-child(2) > #navbarDropdown', '.jumbotron-heading > .btn', 2, 2);
});
it('logs in through products', () => {
cy.loginPath(':nth-child(6) > .container > .row > :nth-child(2) > a > .btn', '/products');
cy.manageEntities(':nth-child(2) > #navbarDropdown', '.text-md-right > .btn', 2, 4);
cy.manageEntities(':nth-child(3) > #navbarDropdown', '.jumbotron-heading > .btn', 2, 2);
});
})
\ No newline at end of file
// const baseUrl = Cypress.config('baseUrl');
describe('user journey', () => {
beforeEach(() => {
//cy.visit(baseUrl);
cy.visit(window.location.origin);
})
context('user-not-logged-in', () => {
it('checks services portal', () => {
cy.log(Cypress.env("username"));
cy.navigateToServices(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn');
});
it('checks services portal via image', () => {
cy.navigateToServices(':nth-child(2) > .container > .row > .text-left');
});
it('checks services portal via anchor', () => {
cy.navigateToServices(':nth-child(1) > .nav-link');
});
it('checks resources portal', () => {
//cy.get(':nth-child(2) > .nav-link').click();
cy.navigateToResources(':nth-child(3) > .container > .row > .order-md-1 > a > .btn');
});
it('checks resources portal via image', () => {
cy.navigateToResources(':nth-child(3) > .container > .row > .order-md-2 > a > .img-fluid');
})
it('checks resources portal via anchor', () => {
cy.navigateToResources(':nth-child(2) > .nav-link');
});
it('checks testing portal', () => {
cy.navigateToTesting(':nth-child(5) > .container > .row > .order-md-1 > a > .btn');
});
it('checks testing via image', () => {
cy.navigateToTesting(':nth-child(5) > .container > .row > .order-md-2 > a > .img-fluid');
})
it('checks testing portal via anchor', () => {
cy.navigateToTesting(':nth-child(4) > .nav-link')
});
it('checks products portal', () => {
cy.navigateToProducts(':nth-child(6) > .container > .row > :nth-child(2) > a > .btn');
});
it('checks products portal via image', () => {
cy.navigateToProducts(':nth-child(6) > .container > .row > .text-left > a > .img-fluid');
})
it('checks products portal via anchor', () => {
cy.navigateToProducts(':nth-child(5) > .nav-link');
})
});
context('<who we are> links', () => {
beforeEach(() => {
cy.get('[id="contact"]').scrollIntoView().should('be.visible');
})
it('checks ETSI SDG OpenSlice Link', () => {
cy.get('.ng-star-inserted > :nth-child(1) > .text-white').click();
cy.origin('https://osl.etsi.org/', () => {
cy.location("pathname").should("equal", "/");
});
});
it("checks OpenSLice by ETSI wiki", () => {
cy.get(':nth-child(3) > .text-white').click();
cy.origin('https://osl.etsi.org/', () => {
cy.location("pathname").should("equal", "/documentation/latest/");
});
});
it('checks <our wiki> link', () => {
cy.get('.col-12 > :nth-child(3) > .font-weight-bold').click();
cy.origin('https://osl.etsi.org/', () => {
cy.location("pathname").should("equal", "/documentation/latest/");
});
});
it('checks linkedin link', () => {
cy.get(':nth-child(2) > .ng-star-inserted > :nth-child(1)').click();
cy.origin('https://www.linkedin.com/company/openslice', ()=> {
cy.location("pathname").should("equal", "/company/openslice");
});
});
it('checks slack link', () => {
cy.get(':nth-child(2) > .ng-star-inserted > :nth-child(2)').click();
cy.origin('https://openslice.slack.com/', () => {
cy.location("pathname").should("equal", "/");
});
});
//twitter test cannot pass, depends on user login
it('checks twitter link', () => {
cy.get(':nth-child(2) > .ng-star-inserted > :nth-child(3)').click();
cy.origin('https://x.com/OpensliceOSS', () => {
cy.location("pathname").should("satisfy", (url) => {
return url === '/OpensliceOSS' || url === '/i/flow/login';
})
});
});
it('checks ecosystem link', () => {
cy.get('.col-md-10 > :nth-child(1) > a').click();
cy.origin('https://osl.etsi.org/ecosystem/', () => {
cy.location("pathname").should("equal", "/ecosystem/");
});
});
it('checks osl etsi link', () => {
cy.get('[target="_blank"]').click();
cy.location("pathname").should("equal", "/")
})
});
})
\ No newline at end of file
{
"routes": [
"resources/resource_catalogs",
"resources/resource_categories",
"resources/resource_categories_update",
"resources/resource_specs",
"resources/resource_spec_update",
"resources/resource_inventory",
"resources/resource_pools",
"resources/resource_pool",
"resources/resource_reservations",
"resources/resource_reservations_calendar",
"resources/resource_reservation_update",
"services/service_catalogs",
"services/service_categories",
"services/service_categories_update",
"services/service_specs",
"services/service_spec_update",
"services/list_nsds",
"services/list_tests",
"services/service_orders",
"services/service_order_checkout",
"services/my_service_orders",
"services/service_orders_calendar",
"services/organizations",
"services/organization_update",
"services/individuals",
"services/individual_update",
"services/service_inventory",
"services/alarms",
"services/action_specs",
"services/action_specs",
"services/action_rules",
"services/action_rule",
"services/service_rule_design",
"testing/service_test_specs",
"testing/service_test_spec",
"testing/service_tests",
"testing/organizations",
"testing/organization_update",
"testing/individuals",
"testing/individual_update",
"products/product_catalogs",
"products/product_catalog_update",
"products/product_categories",
"products/product_category_update",
"products/product_offerings",
"products/product_offering_update",
"products/product_specs",
"products/product_spec_update",
"products/organizations",
"products/organization_update",
"products/individuals",
"products/individual_update",
"/products/individual_update/myuser",
"/testing/individual_update/myuser",
"/services/individual_update/myuser",
"/resources/individual_update/myuser"
]
}
\ No newline at end of file
declare namespace Cypress {
interface Chainable {
navigateToServices(selector): Chainable<any>,
navigateToResources(selector): Chainable<any>,
navigateToTesting(selector): Chainable<any>,
navigateToProducts(selector): Chainable<any>,
authUser(): Chainable<any>,
loginPath(selector, path): Chainable<any>,
manageEntities(selector, button, scndIndx, numOfItems): Chainable<any>,
checkProtectedRoutes(): Chainable<any>
}
}
Cypress.Commands.add('navigateToServices', (selector) => {
cy.get(selector).click();
cy.location("pathname").should("equal", "/services");
cy.get('.btn').should("contain", "Sign In");
cy.get(':nth-child(2) > .nav-item > .nav-link').should("exist");
//service marketplace button should exist and should redirect to /services_marketplace
cy.get('.mr-auto > .nav-item > .nav-link').click();
cy.get('.jumbotron > h5.ng-tns-c147-1').should("contain", "Browse available services and sign in to order");
cy.get('.catalog-tree-header').should("exist");
//sign in button should exist
cy.get(':nth-child(2) > .nav-item > .nav-link').click();
//sign in button should redirect to auth form
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
});
});
Cypress.Commands.add('navigateToResources', (selector) => {
cy.get(selector).click();
cy.location("pathname").should("equal", "/resources");
//sign in button should exist
cy.get('.btn').should('exist').click();
//cy.get('nav-link').should('exist').click();
//sign in button should redirect to auth form
cy.origin('https://portal.openslice.eu/', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
});
})
Cypress.Commands.add('navigateToTesting', (selector) => {
cy.get(selector).click();
cy.location("pathname").should("equal", "/testing");
//sign in button should exist
cy.get('.btn').should('exist').click();
//cy.get('nav-link').should('exist').click();
//sign in button should redirect to auth form
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
});
});
Cypress.Commands.add('navigateToProducts', (selector) => {
cy.get(selector).click();
cy.location("pathname").should("equal", "/products");
cy.get('.btn').should("contain", "Sign In");
cy.get(':nth-child(2) > .nav-item > .nav-link').should("exist");
//marketplace button should exist and should redirect to products/marketplace
cy.get('.mr-auto > .nav-item > .nav-link').click();
cy.get('.catalog-tree-header').should("exist");
cy.get('.mb-0').should("contain", "Product Catalog Explorer");
//sign in button should exist
cy.get(':nth-child(2) > .nav-item > .nav-link').click();
//sign in button should redirect to auth form
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
});
});
Cypress.Commands.add('authUser', () => {
cy.get('.btn').should("contain", "Sign In").click();
cy.origin('https://portal.openslice.eu', () => {
cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth");
cy.get('#username').type(Cypress.env('username'));
cy.get('#password').type(Cypress.env('password'));
cy.get('#kc-login').click();
});
//redirect page
cy.location("pathname").should("equal", "/redirect");
});
Cypress.Commands.add('loginPath', (selector, path) => {
cy.get(selector).click();
cy.intercept(path);
cy.location("pathname").should("equal", path);
cy.authUser();
})
Cypress.Commands.add('manageEntities', (selector, button, scndIndx, numOfItems) => {
for(let i=1; i<=numOfItems; i++) {
cy.get(selector).click();
if(i == 2 && scndIndx == 3){
cy.get(`.nav-item.show > .dropdown-menu > :nth-child(3) > .dropdown-item`).click();
cy.go('back');
}
else
cy.get(`.nav-item.show > .dropdown-menu > :nth-child(${i}) > .dropdown-item`).click();
cy.get(button).click();
cy.go('back');
}
})
Cypress.Commands.add('checkProtectedRoutes', () => {
for(let route of Cypress.env('protectedRoutes')) {
cy.intercept(route);
cy.log(route);
cy.visit(route);
cy.location("pathname").should("equal", "/");
}
})
\ No newline at end of file
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -7,7 +7,12 @@ ...@@ -7,7 +7,12 @@
"build": "ng build", "build": "ng build",
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"e2e": "ng e2e" "e2e": "ng e2e",
"extract-paths": "npx tsx scripts/extract.paths.ts",
"cypress:open": "npm run extract-paths && cypress open",
"cypress:run": "npm run extract-paths && cypress run",
"cy:open": "npm run extract-paths && concurrently \"ng serve\" \"wait-on http://localhost:4200 && cypress open\"",
"cy:run": "npm run extract-paths && concurrently \"ng serve\" \"wait-on http://localhost:4200 && cypress run\""
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
...@@ -38,6 +43,8 @@ ...@@ -38,6 +43,8 @@
"angular-oauth2-oidc": "~13.0.1", "angular-oauth2-oidc": "~13.0.1",
"blockly": "git://github.com/google/blockly.git#6.20210701.0", "blockly": "git://github.com/google/blockly.git#6.20210701.0",
"bootstrap": "~4.6.0", "bootstrap": "~4.6.0",
"concurrently": "^9.1.2",
"dotenv": "^16.4.7",
"jsoneditor": "^9.10.0", "jsoneditor": "^9.10.0",
"jwt-decode": "~2.2.0", "jwt-decode": "~2.2.0",
"ngx-markdown": "~13.1.0", "ngx-markdown": "~13.1.0",
...@@ -52,10 +59,12 @@ ...@@ -52,10 +59,12 @@
"@angular/cli": "~13.3.9", "@angular/cli": "~13.3.9",
"@angular/compiler-cli": "~13.3.11", "@angular/compiler-cli": "~13.3.11",
"@angular/language-service": "~13.3.11", "@angular/language-service": "~13.3.11",
"@cypress/schematic": "^2.4.0",
"@types/jasmine": "~3.3.8", "@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "~2.0.3",
"@types/node": "~12.11.1", "@types/node": "~12.11.1",
"codelyzer": "~6.0.2", "codelyzer": "~6.0.2",
"cypress": "^14.1.0",
"jasmine-core": "~3.5.0", "jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.0", "jasmine-spec-reporter": "~5.0.0",
"karma": "~6.4.1", "karma": "~6.4.1",
...@@ -67,6 +76,8 @@ ...@@ -67,6 +76,8 @@
"protractor": "~7.0.0", "protractor": "~7.0.0",
"ts-node": "~7.0.0", "ts-node": "~7.0.0",
"tslint": "~6.1.0", "tslint": "~6.1.0",
"typescript": "~4.6.4" "tsx": "^4.19.3",
"typescript": "~4.6.4",
"wait-on": "^8.0.2"
} }
} }
import { dirname, join } from "path";
import { writeFileSync, existsSync, mkdirSync, readFileSync } from "fs";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const routesFilePathResources = join(__dirname, "../src/app/app-resources-routing.module.ts");
const routesFilePathTesting = join(__dirname, "../src/app/app-testing-routing.module.ts");
const routesFilePathServices = join(__dirname, "../src/app/app-services-routing.module.ts");
const routesFilePathProducts = join(__dirname, "../src/app/app-products-routing.module.ts");
//read route module files as plaintext and extract paths
function extractRoutesFromFile(filePath: string, parent: string): string[] {
try {
const fileContent = readFileSync(filePath, "utf-8");
// Regex to match route paths (excluding those with `/:id`)
const pathRegex = /path:\s*['"]([^'":]+)['"]/g;
let match;
const paths: string[] = [];
while ((match = pathRegex.exec(fileContent)) !== null) {
if (!match[1].includes("/:id")) {
paths.push(`${parent}/${match[1]}`);
}
}
return paths;
} catch (error) {
console.error(`❌ Error reading file: ${filePath}`, error);
return [];
}
}
// Extract paths from every file
let resourceRoutesStr = extractRoutesFromFile(routesFilePathResources, "resources");
let servicesRoutesStr = extractRoutesFromFile(routesFilePathServices, "services");
let testingRoutesStr = extractRoutesFromFile(routesFilePathTesting, "testing");
let productRoutesStr = extractRoutesFromFile(routesFilePathProducts, "products");
let allRoutes = resourceRoutesStr.concat(servicesRoutesStr, testingRoutesStr, productRoutesStr);
allRoutes.push('/products/individual_update/myuser', '/testing/individual_update/myuser', '/services/individual_update/myuser', '/resources/individual_update/myuser');
let protectedRoutes: string[] = allRoutes.filter((el) => { return el!='services/services_marketplace' && el!='products/marketplace'
&& el!='resources/resources_marketplace'})
// Ensure `cypress/fixtures` directory exists
const fixturesDir = join(__dirname, "../cypress/fixtures");
if (!existsSync(fixturesDir)) {
mkdirSync(fixturesDir, { recursive: true });
}
// Convert extracted routes to JSON and save to file
const jsonOutput = JSON.stringify({ routes: protectedRoutes }, null, 2);
const outputPath = join(fixturesDir, "routes.json");
writeFileSync(outputPath, jsonOutput, "utf-8");
console.log("✅ Routes JSON file generated successfully!");