Skip to content

Commit

Permalink
feat(ips): init ips react app
Browse files Browse the repository at this point in the history
ref: MANAGER-15657

Signed-off-by: Quentin Pavy <[email protected]>
  • Loading branch information
Quentin Pavy committed Oct 23, 2024
1 parent 88dfeea commit 635799a
Show file tree
Hide file tree
Showing 50 changed files with 1,275 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/manager/apps/ips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @ovh-ux/manager-ips-app

> ips manager app
20 changes: 20 additions & 0 deletions packages/manager/apps/ips/cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const isCI = process.env.CI;

module.exports = {
default: {
paths: ['e2e/features/**/*.feature'],
require: [
'../../../../playwright-helpers/bdd-setup.ts',
'e2e/**/*.step.ts',
],
requireModule: ['ts-node/register'],
format: [
'summary',
isCI ? 'progress' : 'progress-bar',
!isCI && ['html', 'e2e/reports/cucumber-results-report.html'],
!isCI && ['usage-json', 'e2e/reports/cucumber-usage-report.json'],
].filter(Boolean),
formatOptions: { snippetInterface: 'async-await' },
retry: 1,
},
};
12 changes: 12 additions & 0 deletions packages/manager/apps/ips/e2e/features/error.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Feature: Error

Scenario Outline: Display an error if request fails
Given The service to fetch the data is <apiOk>
When User navigates to Home page
Then User "<sees>" the list of data
Then User sees <anyError> error

Examples:
| apiOk | sees | anyError |
| OK | sees | no |
| KO | doesn't see | an |
7 changes: 7 additions & 0 deletions packages/manager/apps/ips/e2e/features/onboarding.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: Onboarding page

Scenario: User wants to find informations related to ips
Given User has 0 elements in the Listing page
When User navigates to Listing page
Then User gets redirected to Onboarding page
Then User sees 3 guides
53 changes: 53 additions & 0 deletions packages/manager/apps/ips/e2e/step-definitions/error.step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
import { ICustomWorld } from '../../../../../../playwright-helpers';
import { ConfigParams, getUrl, setupNetwork } from '../utils';
import { title } from '../../public/translations/listing/Messages_fr_FR.json';
import {
manager_error_page_title,
manager_error_page_action_home_label,
manager_error_page_action_reload_label,
} from '../../public/translations/ips/error/Messages_fr_FR.json';

Given('The service to fetch the data is {word}', function(
this: ICustomWorld<ConfigParams>,
apiState: 'OK' | 'KO',
) {
this.handlersConfig.isKo = apiState === 'KO';
});

When('User navigates to Home page', async function(
this: ICustomWorld<ConfigParams>,
) {
await setupNetwork(this);
await this.page.goto(this.testContext.initialUrl || getUrl('root'), {
waitUntil: 'load',
});
});

Then('User {string} the list of data', async function(
this: ICustomWorld<ConfigParams>,
see: 'sees' | "doesn't see",
) {
if (see === 'sees') {
const titleElement = await this.page.getByText(title);
await expect(titleElement).toBeVisible();
}
});

Then('User sees {word} error', async function(
this: ICustomWorld<ConfigParams>,
anyError: 'an' | 'no',
) {
if (anyError === 'an') {
await expect(this.page.getByText(manager_error_page_title)).toBeVisible();

await expect(
this.page.getByText(manager_error_page_action_home_label),
).toBeVisible();

await expect(
this.page.getByText(manager_error_page_action_reload_label),
).toBeVisible();
}
});
32 changes: 32 additions & 0 deletions packages/manager/apps/ips/e2e/step-definitions/onboarding.step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
import { ICustomWorld } from '../../../../../../playwright-helpers';
import { ConfigParams, getUrl, setupNetwork } from '../utils';

Given('User has {int} elements in the Listing page', function(
this: ICustomWorld<ConfigParams>,
nb: number,
) {
this.handlersConfig.nb = nb;
});

When('User navigates to Listing page', async function(
this: ICustomWorld<ConfigParams>,
) {
await setupNetwork(this);
await this.page.goto(getUrl('listing'), { waitUntil: 'load' });
});

Then('User gets redirected to Onboarding page', async function(
this: ICustomWorld<ConfigParams>,
) {
await expect(this.page).toHaveURL(getUrl('onboarding'));
});

Then('User sees {int} guides', async function(
this: ICustomWorld<ConfigParams>,
nbGuides: number,
) {
const guides = await this.page.locator('osds-tile');
await expect(guides).toHaveCount(nbGuides);
});
7 changes: 7 additions & 0 deletions packages/manager/apps/ips/e2e/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { urls } from '../../src/routes/routes.constant';

export const appUrl = 'http://localhost:9001/app';

export type AppRoute = keyof typeof urls;

export const getUrl = (route: AppRoute) => `${appUrl}/#${urls[route]}`;
2 changes: 2 additions & 0 deletions packages/manager/apps/ips/e2e/utils/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './network';
export * from './constants';
28 changes: 28 additions & 0 deletions packages/manager/apps/ips/e2e/utils/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { BrowserContext } from '@playwright/test';
import {
ICustomWorld,
toPlaywrightMockHandler,
Handler,
} from '../../../../../../playwright-helpers';
import {
GetAuthenticationMocks,
getAuthenticationMocks,
} from '../../../../../../playwright-helpers/mocks/auth';
import { getExampleMocks, GetExampleMocksParams } from '../../mocks';

export type ConfigParams = GetAuthenticationMocks & GetExampleMocksParams;

export const getConfig = (params: ConfigParams): Handler[] =>
[getAuthenticationMocks, getExampleMocks].flatMap((getMocks) =>
getMocks(params),
);

export const setupNetwork = async (world: ICustomWorld) =>
Promise.all(
getConfig({
...((world?.handlersConfig as ConfigParams) || ({} as ConfigParams)),
isAuthMocked: true,
})
.reverse()
.map(toPlaywrightMockHandler(world.context as BrowserContext)),
);
22 changes: 22 additions & 0 deletions packages/manager/apps/ips/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="mobile-web-app-capable" content="yes" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>OVHcloud</title>
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="apple-touch-icon" href="images/touchicon-180.png" />
</head>
<body>
<noscript>
<strong>
We're sorry but this application doesn't work properly without
JavaScript enabled. Please enable it to continue.
</strong>
</noscript>
<div id="root"></div>
<script type="module" src="./src/index.tsx"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions packages/manager/apps/ips/mocks/example/example-data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"id": 20374
},
{
"id": 20375
},
{
"id": 20379
}
]
30 changes: 30 additions & 0 deletions packages/manager/apps/ips/mocks/example/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Handler } from '../../../../../../playwright-helpers';
import exampleList from './example-data.json';

export type GetExampleMocksParams = { isKo?: boolean; nb?: number };

export const getExampleMocks = ({
isKo,
nb = Number.POSITIVE_INFINITY,
}: GetExampleMocksParams): Handler[] => [
{
url: '*',
response: isKo
? {
message: 'Example error',
}
: exampleList.slice(0, nb),
status: isKo ? 500 : 200,
api: 'v6',
},
{
url: '*',
response: isKo
? {
message: 'Example error',
}
: exampleList.slice(0, nb),
status: isKo ? 500 : 200,
api: 'v2',
},
];
1 change: 1 addition & 0 deletions packages/manager/apps/ips/mocks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './example/example';
59 changes: 59 additions & 0 deletions packages/manager/apps/ips/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "@ovh-ux/manager-ips-app",
"version": "0.0.0",
"private": true,
"description": "ips manager app",
"repository": {
"type": "git",
"url": "git+https://github.com/ovh/manager.git",
"directory": "packages/manager/apps/ips"
},
"license": "BSD-3-Clause",
"author": "OVH SAS",
"scripts": {
"build": "tsc && vite build",
"dev": "tsc && vite",
"start": "lerna exec --stream --scope='@ovh-ux/manager-ips-app' --include-dependencies -- npm run build --if-present",
"start:dev": "lerna exec --stream --scope='@ovh-ux/manager-ips-app' --include-dependencies -- npm run dev --if-present",
"start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-ips-app' --include-dependencies -- npm run dev:watch --if-present",
"test:e2e": "tsc && node ../../../../scripts/run-playwright-bdd.js",
"test:e2e:ci": "tsc && node ../../../../scripts/run-playwright-bdd.js --ci"
},
"dependencies": {
"@ovh-ux/manager-config": "*",
"@ovh-ux/manager-core-api": "*",
"@ovh-ux/manager-core-utils": "*",
"@ovh-ux/manager-react-components": "*",
"@ovh-ux/manager-react-core-application": "*",
"@ovh-ux/manager-react-shell-client": "*",
"@ovh-ux/manager-tailwind-config": "*",
"@ovh-ux/request-tagger": "*",
"@ovhcloud/ods-common-core": "17.2.1",
"@ovhcloud/ods-common-theming": "17.2.1",
"@ovhcloud/ods-components": "17.2.1",
"@ovhcloud/ods-theme-blue-jeans": "17.2.1",
"@tanstack/react-query": "^5.51.21",
"@tanstack/react-query-devtools": "^5.51.21",
"axios": "^1.1.2",
"clsx": "^1.2.1",
"i18next": "^23.8.2",
"i18next-http-backend": "^2.4.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-router-dom": "^6.3.0",
"tailwindcss": "^3.4.4"
},
"devDependencies": {
"@cucumber/cucumber": "^10.3.1",
"@ovh-ux/manager-vite-config": "*",
"@playwright/test": "^1.41.2",
"typescript": "^5.1.6",
"vite": "^5.2.13"
},
"regions": [
"CA",
"EU",
"US"
]
}
20 changes: 20 additions & 0 deletions packages/manager/apps/ips/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineConfig } from '@playwright/test';

export default defineConfig({
workers: 3,
fullyParallel: false,
timeout: 30 * 1000,
reporter: [['html', { open: 'on-failure' }]],
expect: {
timeout: 20000,
},
use: {
// Collect trace when retrying the failed test.
trace: 'retain-on-failure',
},
testMatch: '**/*.e2e.ts',
webServer: {
command: 'yarn run dev',
url: 'http://localhost:9000/',
},
});
6 changes: 6 additions & 0 deletions packages/manager/apps/ips/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"title": "Dashboard page",
"error_service": "No services info",
"general_informations": "Informations générales",
"tab2": "Tab 2",
"back_link": "Retour à la liste"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"title": "Bienvenue uapp",
"crumb": "ips",
"tabs_2": "Tabs 2",
"onboarding": "Onboarding"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"manager_error_page_title": "Oops …!",
"manager_error_page_button_cancel": "Annuler",
"manager_error_page_detail_code": "Code d'erreur : ",
"manager_error_page_action_reload_label": "Réessayer",
"manager_error_page_action_home_label": "Retour à la page d'accueil",
"manager_error_page_default": "Une erreur est survenue lors du chargement de la page."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"title": "Listing page",
"listing_resultats": "résultats"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"title": "ips",
"description": "Découvrez des services de stockage managés qui s’appuient sur le système de fichiers OpenZFS. Bénéficiez en quelques clics d’espaces de stockage centralisés pour entreposer ou sauvegarder vos données et fichiers.",
"orderButtonLabel": "Commander un ips",
"moreInfoButtonLabel": "En savoir plus sur ips",
"guideCategory": "Tutoriel",
"guide1Title": "Premiers pas avec un ips",
"guide1Description": "Découvrez comment gérer un NAS-HA depuis l'espace-client OVHcloud",
"guide2Title": "Monter votre NAS via un partage NFS",
"guide2Description": "Découvrez comment monter un NAS via un partage NFS",
"guide3Title": "Monter votre NAS sur Windows Server via CIFS",
"guide3Description": "Découvrez comment monter un NAS sur Windows Server via le protocole CIFS"
}
Loading

0 comments on commit 635799a

Please sign in to comment.