2023-04-04 10:46:28 +02:00
|
|
|
///<reference path="../../global.d.ts" />
|
2023-03-29 13:47:12 +02:00
|
|
|
import {
|
|
|
|
BATCH_ACTIONS_BAR,
|
|
|
|
BATCH_SELECT,
|
|
|
|
BATCH_SELECTED_COUNT,
|
|
|
|
MORE_BATCH_ACTIONS,
|
|
|
|
SEARCH_INPUT,
|
2023-04-04 10:46:28 +02:00
|
|
|
//@ts-ignore
|
2023-03-29 13:47:12 +02:00
|
|
|
} from '../../../src/utils/testIds';
|
|
|
|
|
|
|
|
describe('project overview', () => {
|
2023-04-05 13:20:58 +02:00
|
|
|
const randomId = String(Math.random()).split('.')[1];
|
|
|
|
const featureTogglePrefix = 'unleash-e2e-project-overview';
|
|
|
|
const featureToggleName = `${featureTogglePrefix}-${randomId}`;
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
const projectName = `unleash-e2e-project-overview-${randomId}`;
|
2023-04-05 13:20:58 +02:00
|
|
|
const baseUrl = Cypress.config().baseUrl;
|
2024-01-31 08:22:26 +01:00
|
|
|
const selectAll = '[title="Select all rows"] input[type="checkbox"]';
|
2023-04-05 13:20:58 +02:00
|
|
|
|
2023-03-29 13:47:12 +02:00
|
|
|
before(() => {
|
2023-04-04 10:46:28 +02:00
|
|
|
cy.runBefore();
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.login_UI();
|
|
|
|
cy.createProject_API(projectName);
|
2023-03-29 13:47:12 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
after(() => {
|
|
|
|
cy.request({
|
|
|
|
method: 'DELETE',
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
url: `${baseUrl}/api/admin/projects/${projectName}/features/${featureToggleName}-A`,
|
2023-03-29 13:47:12 +02:00
|
|
|
failOnStatusCode: false,
|
|
|
|
});
|
|
|
|
cy.request({
|
|
|
|
method: 'DELETE',
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
url: `${baseUrl}/api/admin/projects/${projectName}/features/${featureToggleName}-B`,
|
2023-03-29 13:47:12 +02:00
|
|
|
failOnStatusCode: false,
|
|
|
|
});
|
|
|
|
cy.request({
|
|
|
|
method: 'DELETE',
|
|
|
|
url: `${baseUrl}/api/admin/archive/${featureToggleName}-A`,
|
|
|
|
});
|
|
|
|
cy.request({
|
|
|
|
method: 'DELETE',
|
|
|
|
url: `${baseUrl}/api/admin/archive/${featureToggleName}-B`,
|
|
|
|
});
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.deleteProject_API(projectName);
|
2023-03-29 13:47:12 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it('loads the table', () => {
|
2023-04-04 10:46:28 +02:00
|
|
|
cy.login_UI();
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.createFeature_API(`${featureToggleName}-A`, projectName);
|
|
|
|
cy.createFeature_API(`${featureToggleName}-B`, projectName);
|
|
|
|
cy.visit(`/projects/${projectName}`);
|
2023-03-29 13:47:12 +02:00
|
|
|
|
|
|
|
// Use search to filter feature toggles and check that the feature toggle is listed in the table.
|
2023-09-29 09:18:51 +02:00
|
|
|
cy.get(`[data-testid="${SEARCH_INPUT}"]`).as('search').click();
|
|
|
|
cy.get('@search').type(featureToggleName);
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get('table').contains('td', `${featureToggleName}-A`);
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get('table tbody tr').should((elements) => {
|
|
|
|
expect(elements).to.have.length.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it('can select and deselect feature toggles', () => {
|
2023-04-04 10:46:28 +02:00
|
|
|
cy.login_UI();
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.visit(`/projects/${projectName}`);
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.viewport(1920, 1080);
|
2023-09-29 09:18:51 +02:00
|
|
|
cy.get(`[data-testid="${SEARCH_INPUT}"]`).as('search').click();
|
|
|
|
cy.get('@search').type(featureToggleName);
|
2023-09-06 10:50:20 +02:00
|
|
|
cy.get('body').type('{esc}');
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get('table tbody tr').should((elements) => {
|
|
|
|
expect(elements).to.have.length.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
const counter = `[data-testid="${BATCH_SELECTED_COUNT}"]`;
|
|
|
|
|
|
|
|
cy.get(counter).should('not.exist');
|
|
|
|
cy.get(selectAll).click();
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get(counter)
|
|
|
|
.invoke('text')
|
|
|
|
.then((text) => {
|
|
|
|
const number = parseFloat(text);
|
|
|
|
expect(number).to.be.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get(selectAll).click();
|
|
|
|
cy.get(counter).should('not.exist');
|
|
|
|
|
|
|
|
cy.get('table td')
|
|
|
|
.contains(`${featureToggleName}-A`)
|
|
|
|
.closest('tr')
|
|
|
|
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
|
|
|
.click();
|
|
|
|
cy.get(counter).contains('1');
|
|
|
|
|
|
|
|
cy.get('table td')
|
|
|
|
.contains(`${featureToggleName}-A`)
|
|
|
|
.closest('tr')
|
|
|
|
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
|
|
|
.click();
|
|
|
|
cy.get(counter).should('not.exist');
|
|
|
|
cy.get('table td')
|
|
|
|
.contains(`${featureToggleName}-B`)
|
|
|
|
.closest('tr')
|
|
|
|
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
|
|
|
.click();
|
|
|
|
cy.get(counter).contains('1');
|
|
|
|
|
|
|
|
cy.get('table td')
|
|
|
|
.contains(`${featureToggleName}-A`)
|
|
|
|
.closest('tr')
|
|
|
|
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
|
|
|
.click();
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get(counter)
|
|
|
|
.invoke('text')
|
|
|
|
.then((text) => {
|
|
|
|
const number = parseFloat(text);
|
|
|
|
expect(number).to.be.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get('table td')
|
|
|
|
.contains(`${featureToggleName}-B`)
|
|
|
|
.closest('tr')
|
|
|
|
.find(`[data-testid="${BATCH_SELECT}"] input[type="checkbox"]`)
|
|
|
|
.click();
|
|
|
|
cy.get(counter).contains('1');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can mark selected togggles as stale', () => {
|
2023-04-04 10:46:28 +02:00
|
|
|
cy.login_UI();
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.visit(`/projects/${projectName}`);
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.viewport(1920, 1080);
|
2023-09-29 09:18:51 +02:00
|
|
|
cy.get(`[data-testid="${SEARCH_INPUT}"]`).as('search').click();
|
|
|
|
cy.get('@search').type(featureToggleName);
|
2023-09-06 10:50:20 +02:00
|
|
|
cy.get('body').type('{esc}');
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get('table tbody tr').should((elements) => {
|
|
|
|
expect(elements).to.have.length.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get(selectAll).click();
|
|
|
|
|
|
|
|
cy.get(`[data-testid="${MORE_BATCH_ACTIONS}"]`).click();
|
|
|
|
|
|
|
|
cy.get('[role="menuitem"]').contains('Mark as stale').click();
|
|
|
|
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.visit(`/projects/${projectName}/features/${featureToggleName}-A`);
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get('[title="Feature toggle is deprecated."]').should('exist');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can archive selected togggles', () => {
|
2023-04-04 10:46:28 +02:00
|
|
|
cy.login_UI();
|
refactor: isolate tests (#5433)
This PR fixes a race condition between e2e tests where bulk archiving
all toggles in the default project would delete toggles used for the
features e2e tests.
It does by isolating the features.spec and overview.spec to their
respective projects, so that they always operate on isolated data.
### Future enhancements:
I'm not particularly fond of passing the projectName through to all the
helper methods. It complicates the tests more than it should. I would
like to be able to set the project once per test and have all the helper
methods be aware of the context. Something like this should work:
```
before(() => {
cy.wrap('projectId').as('project');
})
```
And in the helpers:
```
export const createFeature_API = (
featureName: string,
options?: Partial<Cypress.RequestOptions>,
): Chainable<any> => {
return cy.get('@project').then((project) => {
projectName = project || 'default';
return cy.request({
url: `${baseUrl}/api/admin/projects/${projectName}/features`,
method: 'POST',
body: {
name: `${featureName}`,
description: 'hello-world',
type: 'release',
impressionData: false,
},
...options,
});
});
};
```
2023-11-27 13:55:44 +01:00
|
|
|
cy.visit(`/projects/${projectName}`);
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.viewport(1920, 1080);
|
2023-09-29 09:18:51 +02:00
|
|
|
cy.get(`[data-testid="${SEARCH_INPUT}"]`).as('search').click();
|
|
|
|
cy.get('@search').type(featureToggleName);
|
2023-09-06 10:50:20 +02:00
|
|
|
cy.get('body').type('{esc}');
|
|
|
|
|
2023-10-05 13:50:46 +02:00
|
|
|
cy.get('table tbody tr').should((elements) => {
|
|
|
|
expect(elements).to.have.length.at.least(2);
|
|
|
|
});
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get(selectAll).click();
|
|
|
|
|
2023-10-23 13:46:59 +02:00
|
|
|
// Ensure button is enabled
|
|
|
|
cy.get(`[data-testid=${BATCH_ACTIONS_BAR}] button`)
|
|
|
|
.contains('Archive')
|
|
|
|
.should('not.have.attr', 'disabled');
|
|
|
|
|
|
|
|
// Separate click action
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get(`[data-testid=${BATCH_ACTIONS_BAR}] button`)
|
|
|
|
.contains('Archive')
|
|
|
|
.click();
|
2023-10-23 13:46:59 +02:00
|
|
|
|
2023-03-29 13:47:12 +02:00
|
|
|
cy.get('p')
|
2023-10-05 13:50:46 +02:00
|
|
|
.contains('Are you sure you want to archive ')
|
2023-03-29 13:47:12 +02:00
|
|
|
.should('exist');
|
|
|
|
cy.get('button').contains('Archive toggles').click();
|
|
|
|
cy.get('table tbody tr').should('have.length', 0);
|
|
|
|
});
|
|
|
|
});
|