1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

refactor: convert auth tests from Cypress to Jest (#864)

* refactor: replace data-test with data-testid

* refactor: add Jest tests for auth pages

* refactor: remove Cypress tests for auth pages

* refactor: remove questionable snapshots

* refactor: share test server setup/teardown

* refactor: restore auth page flex layout

* refactor: use toBeInTheDocument

* refactor: change recent data-test attrs to data-testid
This commit is contained in:
olav 2022-04-08 13:13:45 +02:00 committed by GitHub
parent 1132a79f6d
commit 49b8e7329e
51 changed files with 666 additions and 390 deletions

View File

@ -1,24 +0,0 @@
name: e2e:auth
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows
on: [deployment_status]
jobs:
e2e:
# only runs this job on successful deploy
if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success'
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: |
echo "$GITHUB_CONTEXT"
- name: Checkout
uses: actions/checkout@v3
- name: Run Cypress
uses: cypress-io/github-action@v2
with:
config: baseUrl=${{ github.event.deployment_status.target_url }}
record: true
spec: cypress/integration/auth/auth.spec.ts
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

View File

@ -1,201 +0,0 @@
/// <reference types="cypress" />
export {};
describe('auth', () => {
it('renders the password login', () => {
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
options: [],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/');
cy.intercept('POST', '/auth/simple/login', req => {
expect(req.body.username).to.equal('admin');
expect(req.body.password).to.equal('unleash4all');
}).as('passwordLogin');
cy.wait(1000);
cy.get('[data-test="LOGIN_EMAIL_ID"]').type('admin');
cy.get('[data-test="LOGIN_PASSWORD_ID"]').type('unleash4all');
cy.get("[data-test='LOGIN_BUTTON']").click();
});
it('renders does not render password login if defaultHidden is true', () => {
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
options: [],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist');
cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist');
});
it('renders google auth when options are specified', () => {
const ssoPath = '/auth/google/login';
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
options: [
{
type: 'google',
message: 'Sign in with Google',
path: ssoPath,
},
],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist');
cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist');
cy.get('[data-test="SSO_LOGIN_BUTTON-google"]')
.should('exist')
.should('have.attr', 'href', ssoPath);
});
it('renders oidc auth when options are specified', () => {
const ssoPath = '/auth/oidc/login';
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
options: [
{
type: 'oidc',
message: 'Sign in with OpenId Connect',
path: ssoPath,
},
],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist');
cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist');
cy.get('[data-test="SSO_LOGIN_BUTTON-oidc"]')
.should('exist')
.should('have.attr', 'href', ssoPath);
});
it('renders saml auth when options are specified', () => {
const ssoPath = '/auth/saml/login';
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
options: [
{
type: 'saml',
message: 'Sign in with SAML 2.0',
path: ssoPath,
},
],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist');
cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist');
cy.get('[data-test="SSO_LOGIN_BUTTON-saml"]')
.should('exist')
.should('have.attr', 'href', ssoPath);
});
it('can visit forgot password when password auth is enabled', () => {
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
options: [],
path: '/auth/simple/login',
type: 'password',
},
});
cy.visit('/forgotten-password');
cy.get('[data-test="FORGOTTEN_PASSWORD_FIELD"').type('me@myemail.com');
});
it('renders demo auth correctly', () => {
const email = 'hello@hello.com';
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
options: [],
path: '/auth/demo/login',
type: 'demo',
},
});
cy.intercept('POST', '/auth/demo/login', req => {
expect(req.body.email).to.equal(email);
}).as('passwordLogin');
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').type(email);
cy.get("[data-test='LOGIN_BUTTON']").click();
});
it('renders email auth correctly', () => {
const email = 'hello@hello.com';
cy.intercept('GET', '/api/admin/**', {
statusCode: 401,
body: {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
options: [],
path: '/auth/unsecure/login',
type: 'unsecure',
},
});
cy.intercept('POST', '/auth/unsecure/login', req => {
expect(req.body.email).to.equal(email);
}).as('passwordLogin');
cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').type(email);
cy.get("[data-test='LOGIN_BUTTON']").click();
});
it('renders invalid token page when token is invalid', () => {
cy.visit('/new-user?token=hellotokenworld');
cy.get('[data-test="INVALID_TOKEN_BUTTON"]').should('be.visible');
});
});

View File

@ -42,61 +42,61 @@ describe('feature', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/'); cy.visit('/');
cy.get('[data-test="LOGIN_EMAIL_ID"]').type(AUTH_USER); cy.get('[data-testid="LOGIN_EMAIL_ID"]').type(AUTH_USER);
if (AUTH_PASSWORD) { if (AUTH_PASSWORD) {
cy.get('[data-test="LOGIN_PASSWORD_ID"]').type(AUTH_PASSWORD); cy.get('[data-testid="LOGIN_PASSWORD_ID"]').type(AUTH_PASSWORD);
} }
cy.get("[data-test='LOGIN_BUTTON']").click(); cy.get("[data-testid='LOGIN_BUTTON']").click();
// Wait for the login redirect to complete. // Wait for the login redirect to complete.
cy.get('[data-test=HEADER_USER_AVATAR'); cy.get('[data-testid=HEADER_USER_AVATAR');
}); });
it('can create a feature toggle', () => { it('can create a feature toggle', () => {
if (document.querySelector("[data-test='CLOSE_SPLASH']")) { if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
cy.get("[data-test='CLOSE_SPLASH']").click(); cy.get("[data-testid='CLOSE_SPLASH']").click();
} }
cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click();
cy.intercept('POST', '/api/admin/projects/default/features').as( cy.intercept('POST', '/api/admin/projects/default/features').as(
'createFeature' 'createFeature'
); );
cy.get("[data-test='CF_NAME_ID'").type(featureToggleName); cy.get("[data-testid='CF_NAME_ID'").type(featureToggleName);
cy.get("[data-test='CF_DESC_ID'").type('hello-world'); cy.get("[data-testid='CF_DESC_ID'").type('hello-world');
cy.get("[data-test='CF_CREATE_BTN_ID']").click(); cy.get("[data-testid='CF_CREATE_BTN_ID']").click();
cy.wait('@createFeature'); cy.wait('@createFeature');
cy.url().should('include', featureToggleName); cy.url().should('include', featureToggleName);
}); });
it('gives an error if a toggle exists with the same name', () => { it('gives an error if a toggle exists with the same name', () => {
cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click();
cy.intercept('POST', '/api/admin/projects/default/features').as( cy.intercept('POST', '/api/admin/projects/default/features').as(
'createFeature' 'createFeature'
); );
cy.get("[data-test='CF_NAME_ID'").type(featureToggleName); cy.get("[data-testid='CF_NAME_ID'").type(featureToggleName);
cy.get("[data-test='CF_DESC_ID'").type('hello-world'); cy.get("[data-testid='CF_DESC_ID'").type('hello-world');
cy.get("[data-test='CF_CREATE_BTN_ID']").click(); cy.get("[data-testid='CF_CREATE_BTN_ID']").click();
cy.get("[data-test='INPUT_ERROR_TEXT']").contains( cy.get("[data-testid='INPUT_ERROR_TEXT']").contains(
'A feature with this name already exists' 'A feature with this name already exists'
); );
}); });
it('gives an error if a toggle name is url unsafe', () => { it('gives an error if a toggle name is url unsafe', () => {
cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click();
cy.intercept('POST', '/api/admin/projects/default/features').as( cy.intercept('POST', '/api/admin/projects/default/features').as(
'createFeature' 'createFeature'
); );
cy.get("[data-test='CF_NAME_ID'").type('featureToggleUnsafe####$#//'); cy.get("[data-testid='CF_NAME_ID'").type('featureToggleUnsafe####$#//');
cy.get("[data-test='CF_DESC_ID'").type('hello-world'); cy.get("[data-testid='CF_DESC_ID'").type('hello-world');
cy.get("[data-test='CF_CREATE_BTN_ID']").click(); cy.get("[data-testid='CF_CREATE_BTN_ID']").click();
cy.get("[data-test='INPUT_ERROR_TEXT']").contains( cy.get("[data-testid='INPUT_ERROR_TEXT']").contains(
`"name" must be URL friendly` `"name" must be URL friendly`
); );
}); });
@ -107,16 +107,16 @@ describe('feature', () => {
); );
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=ROLLOUT_SLIDER_ID') cy.get('[data-testid=ROLLOUT_SLIDER_ID')
.click() .click()
.type('{leftarrow}'.repeat(20)); .type('{leftarrow}'.repeat(20));
if (ENTERPRISE) { if (ENTERPRISE) {
cy.get('[data-test=ADD_CONSTRAINT_ID]').click(); cy.get('[data-testid=ADD_CONSTRAINT_ID]').click();
cy.get('[data-test=CONSTRAINT_AUTOCOMPLETE_ID]') cy.get('[data-testid=CONSTRAINT_AUTOCOMPLETE_ID]')
.type('{downArrow}'.repeat(1)) .type('{downArrow}'.repeat(1))
.type('{enter}'); .type('{enter}');
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
} }
cy.intercept( cy.intercept(
@ -140,7 +140,7 @@ describe('feature', () => {
} }
).as('addStrategyToFeature'); ).as('addStrategyToFeature');
cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click();
cy.wait('@addStrategyToFeature'); cy.wait('@addStrategyToFeature');
}); });
@ -150,18 +150,18 @@ describe('feature', () => {
); );
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=ROLLOUT_SLIDER_ID') cy.get('[data-testid=ROLLOUT_SLIDER_ID')
.click() .click()
.type('{rightArrow}'.repeat(10)); .type('{rightArrow}'.repeat(10));
cy.get('[data-test=FLEXIBLE_STRATEGY_STICKINESS_ID]') cy.get('[data-testid=FLEXIBLE_STRATEGY_STICKINESS_ID]')
.first() .first()
.click() .click()
.get('[data-test=SELECT_ITEM_ID-sessionId') .get('[data-testid=SELECT_ITEM_ID-sessionId')
.first() .first()
.click(); .click();
cy.get('[data-test=FLEXIBLE_STRATEGY_GROUP_ID]') cy.get('[data-testid=FLEXIBLE_STRATEGY_GROUP_ID]')
.first() .first()
.clear() .clear()
.type('new-group-id'); .type('new-group-id');
@ -186,7 +186,7 @@ describe('feature', () => {
} }
).as('updateStrategy'); ).as('updateStrategy');
cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click();
cy.wait('@updateStrategy'); cy.wait('@updateStrategy');
}); });
@ -203,9 +203,11 @@ describe('feature', () => {
} }
).as('deleteStrategy'); ).as('deleteStrategy');
cy.get('[data-test=FEATURE_ENVIRONMENT_ACCORDION_development]').click(); cy.get(
cy.get('[data-test=STRATEGY_FORM_REMOVE_ID]').click(); '[data-testid=FEATURE_ENVIRONMENT_ACCORDION_development]'
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); ).click();
cy.get('[data-testid=STRATEGY_FORM_REMOVE_ID]').click();
cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.wait('@deleteStrategy'); cy.wait('@deleteStrategy');
}); });
@ -215,19 +217,19 @@ describe('feature', () => {
); );
if (ENTERPRISE) { if (ENTERPRISE) {
cy.get('[data-test=ADD_CONSTRAINT_ID]').click(); cy.get('[data-testid=ADD_CONSTRAINT_ID]').click();
cy.get('[data-test=CONSTRAINT_AUTOCOMPLETE_ID]') cy.get('[data-testid=CONSTRAINT_AUTOCOMPLETE_ID]')
.type('{downArrow}'.repeat(1)) .type('{downArrow}'.repeat(1))
.type('{enter}'); .type('{enter}');
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
} }
cy.get('[data-test=STRATEGY_INPUT_LIST]') cy.get('[data-testid=STRATEGY_INPUT_LIST]')
.type('user1') .type('user1')
.type('{enter}') .type('{enter}')
.type('user2') .type('user2')
.type('{enter}'); .type('{enter}');
cy.get('[data-test=ADD_TO_STRATEGY_INPUT_LIST]').click(); cy.get('[data-testid=ADD_TO_STRATEGY_INPUT_LIST]').click();
cy.intercept( cy.intercept(
'POST', 'POST',
@ -249,7 +251,7 @@ describe('feature', () => {
} }
).as('addStrategyToFeature'); ).as('addStrategyToFeature');
cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click();
cy.wait('@addStrategyToFeature'); cy.wait('@addStrategyToFeature');
}); });
@ -278,32 +280,32 @@ describe('feature', () => {
} }
).as('variantCreation'); ).as('variantCreation');
cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); cy.get('[data-testid=ADD_VARIANT_BUTTON]').click();
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName); cy.get('[data-testid=VARIANT_NAME_INPUT]').type(variantName);
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.wait('@variantCreation'); cy.wait('@variantCreation');
cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); cy.get('[data-testid=ADD_VARIANT_BUTTON]').click();
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=VARIANT_NAME_INPUT]').type(secondVariantName); cy.get('[data-testid=VARIANT_NAME_INPUT]').type(secondVariantName);
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.wait('@variantCreation'); cy.wait('@variantCreation');
}); });
it('can set weight to fixed value for one of the variants', () => { it('can set weight to fixed value for one of the variants', () => {
cy.visit(`/projects/default/features/${featureToggleName}/variants`); cy.visit(`/projects/default/features/${featureToggleName}/variants`);
cy.get('[data-test=VARIANT_EDIT_BUTTON]').first().click(); cy.get('[data-testid=VARIANT_EDIT_BUTTON]').first().click();
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=VARIANT_NAME_INPUT]') cy.get('[data-testid=VARIANT_NAME_INPUT]')
.children() .children()
.find('input') .find('input')
.should('have.attr', 'disabled'); .should('have.attr', 'disabled');
cy.get('[data-test=VARIANT_WEIGHT_TYPE]') cy.get('[data-testid=VARIANT_WEIGHT_TYPE]')
.children() .children()
.find('input') .find('input')
.check(); .check();
cy.get('[data-test=VARIANT_WEIGHT_INPUT]').clear().type('15'); cy.get('[data-testid=VARIANT_WEIGHT_INPUT]').clear().type('15');
cy.intercept( cy.intercept(
'PATCH', 'PATCH',
@ -321,9 +323,9 @@ describe('feature', () => {
} }
).as('variantUpdate'); ).as('variantUpdate');
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.wait('@variantUpdate'); cy.wait('@variantUpdate');
cy.get('[data-test=VARIANT_WEIGHT]') cy.get('[data-testid=VARIANT_WEIGHT]')
.first() .first()
.should('have.text', '15 %'); .should('have.text', '15 %');
}); });
@ -332,10 +334,10 @@ describe('feature', () => {
const variantName = 'to-be-deleted'; const variantName = 'to-be-deleted';
cy.visit(`/projects/default/features/${featureToggleName}/variants`); cy.visit(`/projects/default/features/${featureToggleName}/variants`);
cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); cy.get('[data-testid=ADD_VARIANT_BUTTON]').click();
cy.wait(1000); cy.wait(1000);
cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName); cy.get('[data-testid=VARIANT_NAME_INPUT]').type(variantName);
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.intercept( cy.intercept(
'PATCH', 'PATCH',
@ -348,8 +350,8 @@ describe('feature', () => {
} }
).as('delete'); ).as('delete');
cy.get(`[data-test=VARIANT_DELETE_BUTTON_${variantName}]`).click(); cy.get(`[data-testid=VARIANT_DELETE_BUTTON_${variantName}]`).click();
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
cy.wait('@delete'); cy.wait('@delete');
}); });
}); });

View File

@ -25,52 +25,52 @@ describe('segments', () => {
cy.session(AUTH_USER, () => { cy.session(AUTH_USER, () => {
cy.visit('/'); cy.visit('/');
cy.wait(1000); cy.wait(1000);
cy.get("[data-test='LOGIN_EMAIL_ID']").type(AUTH_USER); cy.get("[data-testid='LOGIN_EMAIL_ID']").type(AUTH_USER);
if (AUTH_PASSWORD) { if (AUTH_PASSWORD) {
cy.get("[data-test='LOGIN_PASSWORD_ID']").type(AUTH_PASSWORD); cy.get("[data-testid='LOGIN_PASSWORD_ID']").type(AUTH_PASSWORD);
} }
cy.get("[data-test='LOGIN_BUTTON']").click(); cy.get("[data-testid='LOGIN_BUTTON']").click();
// Wait for the login redirect to complete. // Wait for the login redirect to complete.
cy.get("[data-test='HEADER_USER_AVATAR']"); cy.get("[data-testid='HEADER_USER_AVATAR']");
}); });
cy.visit('/segments'); cy.visit('/segments');
}); });
it('can create a segment', () => { it('can create a segment', () => {
if (document.querySelector("[data-test='CLOSE_SPLASH']")) { if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
cy.get("[data-test='CLOSE_SPLASH']").click(); cy.get("[data-testid='CLOSE_SPLASH']").click();
} }
cy.get("[data-test='NAVIGATE_TO_CREATE_SEGMENT']").click(); cy.get("[data-testid='NAVIGATE_TO_CREATE_SEGMENT']").click();
cy.intercept('POST', '/api/admin/segments').as('createSegment'); cy.intercept('POST', '/api/admin/segments').as('createSegment');
cy.get("[data-test='SEGMENT_NAME_ID']").type(segmentName); cy.get("[data-testid='SEGMENT_NAME_ID']").type(segmentName);
cy.get("[data-test='SEGMENT_DESC_ID']").type('hello-world'); cy.get("[data-testid='SEGMENT_DESC_ID']").type('hello-world');
cy.get("[data-test='SEGMENT_NEXT_BTN_ID']").click(); cy.get("[data-testid='SEGMENT_NEXT_BTN_ID']").click();
cy.get("[data-test='SEGMENT_CREATE_BTN_ID']").click(); cy.get("[data-testid='SEGMENT_CREATE_BTN_ID']").click();
cy.wait('@createSegment'); cy.wait('@createSegment');
cy.contains(segmentName); cy.contains(segmentName);
}); });
it('gives an error if a segment exists with the same name', () => { it('gives an error if a segment exists with the same name', () => {
cy.get("[data-test='NAVIGATE_TO_CREATE_SEGMENT']").click(); cy.get("[data-testid='NAVIGATE_TO_CREATE_SEGMENT']").click();
cy.get("[data-test='SEGMENT_NAME_ID']").type(segmentName); cy.get("[data-testid='SEGMENT_NAME_ID']").type(segmentName);
cy.get("[data-test='SEGMENT_NEXT_BTN_ID']").should('be.disabled'); cy.get("[data-testid='SEGMENT_NEXT_BTN_ID']").should('be.disabled');
cy.get("[data-test='INPUT_ERROR_TEXT']").contains( cy.get("[data-testid='INPUT_ERROR_TEXT']").contains(
'Segment name already exists' 'Segment name already exists'
); );
}); });
it('can delete a segment', () => { it('can delete a segment', () => {
cy.get(`[data-test='SEGMENT_DELETE_BTN_ID_${segmentName}']`).click(); cy.get(`[data-testid='SEGMENT_DELETE_BTN_ID_${segmentName}']`).click();
cy.get("[data-test='SEGMENT_DIALOG_NAME_ID']").type(segmentName); cy.get("[data-testid='SEGMENT_DIALOG_NAME_ID']").type(segmentName);
cy.get("[data-test='DIALOGUE_CONFIRM_ID'").click(); cy.get("[data-testid='DIALOGUE_CONFIRM_ID'").click();
cy.contains(segmentName).should('not.exist'); cy.contains(segmentName).should('not.exist');
}); });

View File

@ -68,6 +68,7 @@
"http-proxy-middleware": "2.0.4", "http-proxy-middleware": "2.0.4",
"immer": "^9.0.12", "immer": "^9.0.12",
"lodash.clonedeep": "4.5.0", "lodash.clonedeep": "4.5.0",
"msw": "^0.39.2",
"prettier": "2.6.1", "prettier": "2.6.1",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "17.0.2", "react": "17.0.2",

View File

@ -247,7 +247,7 @@ export const ApiTokenList = () => {
'/admin/api/create-token' '/admin/api/create-token'
) )
} }
data-test={CREATE_API_TOKEN_BUTTON} data-testid={CREATE_API_TOKEN_BUTTON}
> >
New API token New API token
</Button> </Button>

View File

@ -81,7 +81,7 @@ const Dialogue: React.FC<IDialogue> = ({
onClick={handleClick} onClick={handleClick}
autoFocus={!formId} autoFocus={!formId}
disabled={disabledPrimaryButton} disabled={disabledPrimaryButton}
data-test={DIALOGUE_CONFIRM_ID} data-testid={DIALOGUE_CONFIRM_ID}
type={formId ? 'submit' : 'button'} type={formId ? 'submit' : 'button'}
> >
{primaryButtonText || "Yes, I'm sure"} {primaryButtonText || "Yes, I'm sure"}

View File

@ -52,7 +52,7 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({
key={option.key} key={option.key}
value={option.key} value={option.key}
title={option.title || ''} title={option.title || ''}
data-test={`${SELECT_ITEM_ID}-${option.label}`} data-testid={`${SELECT_ITEM_ID}-${option.label}`}
disabled={option.disabled} disabled={option.disabled}
> >
{option.label} {option.label}

View File

@ -48,7 +48,7 @@ const Input = ({
onChange={onChange} onChange={onChange}
FormHelperTextProps={{ FormHelperTextProps={{
// @ts-expect-error // @ts-expect-error
['data-test']: INPUT_ERROR_TEXT, ['data-testid']: INPUT_ERROR_TEXT,
classes: { classes: {
root: styles.helperText, root: styles.helperText,
}, },

View File

@ -29,7 +29,7 @@ export const SidebarModal = ({
aria-label={label} aria-label={label}
BackdropComponent={Backdrop} BackdropComponent={Backdrop}
BackdropProps={{ timeout: TRANSITION_DURATION }} BackdropProps={{ timeout: TRANSITION_DURATION }}
data-test={SIDEBAR_MODAL_ID} data-testid={SIDEBAR_MODAL_ID}
> >
<Fade timeout={TRANSITION_DURATION} in={open}> <Fade timeout={TRANSITION_DURATION} in={open}>
<div className={styles.modal}>{children}</div> <div className={styles.modal}>{children}</div>

View File

@ -80,7 +80,7 @@ export const FormButtons = ({
}) => ( }) => (
<div> <div>
<Button <Button
data-test={primaryButtonTestId} data-testid={primaryButtonTestId}
type="submit" type="submit"
color="primary" color="primary"
variant="contained" variant="contained"

View File

@ -41,7 +41,7 @@ const SelectMenu: React.FC<ISelectMenuProps> = ({
key={option.key} key={option.key}
value={option.key} value={option.key}
title={option.title || ''} title={option.title || ''}
data-test={`${SELECT_ITEM_ID}-${option.label}`} data-testid={`${SELECT_ITEM_ID}-${option.label}`}
> >
{option.label} {option.label}
</MenuItem> </MenuItem>

View File

@ -105,7 +105,7 @@ const CreateFeature = () => {
name="Feature" name="Feature"
permission={CREATE_FEATURE} permission={CREATE_FEATURE}
projectId={project} projectId={project}
data-test={CF_CREATE_BTN_ID} data-testid={CF_CREATE_BTN_ID}
/> />
</FeatureForm> </FeatureForm>
</FormTemplate> </FormTemplate>

View File

@ -32,7 +32,7 @@ export const CreateFeatureButton = ({
<IconButton <IconButton
component={Link} component={Link}
to={createFeature.path} to={createFeature.path}
data-test={NAVIGATE_TO_CREATE_FEATURE} data-testid={NAVIGATE_TO_CREATE_FEATURE}
disabled={!createFeature.access} disabled={!createFeature.access}
> >
<Add titleAccess="New" /> <Add titleAccess="New" />
@ -45,7 +45,7 @@ export const CreateFeatureButton = ({
color="primary" color="primary"
variant="contained" variant="contained"
component={Link} component={Link}
data-test={NAVIGATE_TO_CREATE_FEATURE} data-testid={NAVIGATE_TO_CREATE_FEATURE}
disabled={!createFeature.access} disabled={!createFeature.access}
className={classnames({ skeleton: loading })} className={classnames({ skeleton: loading })}
> >

View File

@ -84,7 +84,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
onFocus={() => clearErrors()} onFocus={() => clearErrors()}
value={name} value={name}
onChange={e => setName(trim(e.target.value))} onChange={e => setName(trim(e.target.value))}
data-test={CF_NAME_ID} data-testid={CF_NAME_ID}
onBlur={validateToggleName} onBlur={validateToggleName}
/> />
<p className={styles.inputDescription}> <p className={styles.inputDescription}>
@ -97,7 +97,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
label={'Toggle type'} label={'Toggle type'}
id="feature-type-select" id="feature-type-select"
editable editable
data-test={CF_TYPE_ID} data-testid={CF_TYPE_ID}
IconComponent={KeyboardArrowDownOutlined} IconComponent={KeyboardArrowDownOutlined}
className={styles.selectInput} className={styles.selectInput}
/> />
@ -137,7 +137,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
label="Description" label="Description"
placeholder="A short description of the feature toggle" placeholder="A short description of the feature toggle"
value={description} value={description}
data-test={CF_DESC_ID} data-testid={CF_DESC_ID}
onChange={e => setDescription(e.target.value)} onChange={e => setDescription(e.target.value)}
/> />
<FormControl className={styles.input}> <FormControl className={styles.input}>

View File

@ -135,7 +135,7 @@ export const FeatureStrategyForm = ({
color="primary" color="primary"
type="submit" type="submit"
disabled={loading || !hasValidConstraints} disabled={loading || !hasValidConstraints}
data-test={STRATEGY_FORM_SUBMIT_ID} data-testid={STRATEGY_FORM_SUBMIT_ID}
> >
Save strategy Save strategy
</PermissionButton> </PermissionButton>

View File

@ -68,7 +68,7 @@ export const FeatureStrategyRemove = ({
environmentId={environmentId} environmentId={environmentId}
disabled={disabled} disabled={disabled}
permission={DELETE_FEATURE_STRATEGY} permission={DELETE_FEATURE_STRATEGY}
data-test={STRATEGY_FORM_REMOVE_ID} data-testid={STRATEGY_FORM_REMOVE_ID}
type="button" type="button"
> >
<Delete titleAccess="Delete strategy" /> <Delete titleAccess="Delete strategy" />
@ -81,7 +81,7 @@ export const FeatureStrategyRemove = ({
environmentId={environmentId} environmentId={environmentId}
disabled={disabled} disabled={disabled}
permission={DELETE_FEATURE_STRATEGY} permission={DELETE_FEATURE_STRATEGY}
data-test={STRATEGY_FORM_REMOVE_ID} data-testid={STRATEGY_FORM_REMOVE_ID}
color="secondary" color="secondary"
variant="text" variant="text"
type="button" type="button"

View File

@ -89,7 +89,7 @@ const FeatureOverviewEnvironment = ({
<div className={styles.featureOverviewEnvironment}> <div className={styles.featureOverviewEnvironment}>
<Accordion <Accordion
style={{ boxShadow: 'none' }} style={{ boxShadow: 'none' }}
data-test={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`} data-testid={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`}
> >
<AccordionSummary <AccordionSummary
className={styles.accordionHeader} className={styles.accordionHeader}

View File

@ -277,7 +277,7 @@ export const AddVariant = ({
type="name" type="name"
disabled={editing} disabled={editing}
onChange={setVariantValue} onChange={setVariantValue}
data-test={'VARIANT_NAME_INPUT'} data-testid={'VARIANT_NAME_INPUT'}
/> />
<br /> <br />
<Grid container> <Grid container>
@ -299,7 +299,7 @@ export const AddVariant = ({
projectId={projectId} projectId={projectId}
name="weightType" name="weightType"
checked={isFixWeight} checked={isFixWeight}
data-test={ data-testid={
'VARIANT_WEIGHT_TYPE' 'VARIANT_WEIGHT_TYPE'
} }
onChange={setVariantWeightType} onChange={setVariantWeightType}
@ -320,7 +320,7 @@ export const AddVariant = ({
id="weight" id="weight"
label="Weight" label="Weight"
name="weight" name="weight"
data-test={'VARIANT_WEIGHT_INPUT'} data-testid={'VARIANT_WEIGHT_INPUT'}
InputProps={{ InputProps={{
endAdornment: ( endAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
@ -373,7 +373,7 @@ export const AddVariant = ({
className={commonStyles.fullWidth} className={commonStyles.fullWidth}
value={payload.value} value={payload.value}
onChange={onPayload} onChange={onPayload}
data-test={'VARIANT_PAYLOAD_VALUE'} data-testid={'VARIANT_PAYLOAD_VALUE'}
placeholder={ placeholder={
payload.type === 'json' payload.type === 'json'
? '{ "hello": "world" }' ? '{ "hello": "world" }'

View File

@ -292,7 +292,7 @@ const FeatureOverviewVariants = () => {
setShowAddVariant(true); setShowAddVariant(true);
}} }}
className={styles.addVariantButton} className={styles.addVariantButton}
data-test={'ADD_VARIANT_BUTTON'} data-testid={'ADD_VARIANT_BUTTON'}
permission={UPDATE_FEATURE_VARIANTS} permission={UPDATE_FEATURE_VARIANTS}
projectId={projectId} projectId={projectId}
> >

View File

@ -23,7 +23,7 @@ const FeatureVariantListItem = ({
return ( return (
<TableRow> <TableRow>
<TableCell data-test={'VARIANT_NAME'}>{variant.name}</TableCell> <TableCell data-testid={'VARIANT_NAME'}>{variant.name}</TableCell>
<TableCell className={styles.chipContainer}> <TableCell className={styles.chipContainer}>
<ConditionallyRender <ConditionallyRender
condition={Boolean(variant.payload)} condition={Boolean(variant.payload)}
@ -43,10 +43,10 @@ const FeatureVariantListItem = ({
} }
/> />
</TableCell> </TableCell>
<TableCell data-test={'VARIANT_WEIGHT'}> <TableCell data-testid={'VARIANT_WEIGHT'}>
{variant.weight / 10.0} % {variant.weight / 10.0} %
</TableCell> </TableCell>
<TableCell data-test={'VARIANT_WEIGHT_TYPE'}> <TableCell data-testid={'VARIANT_WEIGHT_TYPE'}>
{variant.weightType === FIX ? 'Fix' : 'Variable'} {variant.weightType === FIX ? 'Fix' : 'Variable'}
</TableCell> </TableCell>
<ConditionallyRender <ConditionallyRender
@ -55,13 +55,13 @@ const FeatureVariantListItem = ({
<TableCell className={styles.actions}> <TableCell className={styles.actions}>
<div className={styles.actionsContainer}> <div className={styles.actionsContainer}>
<IconButton <IconButton
data-test={'VARIANT_EDIT_BUTTON'} data-testid={'VARIANT_EDIT_BUTTON'}
onClick={() => editVariant(variant.name)} onClick={() => editVariant(variant.name)}
> >
<Edit /> <Edit />
</IconButton> </IconButton>
<IconButton <IconButton
data-test={`VARIANT_DELETE_BUTTON_${variant.name}`} data-testid={`VARIANT_DELETE_BUTTON_${variant.name}`}
onClick={e => { onClick={e => {
e.stopPropagation(); e.stopPropagation();
setDelDialog({ setDelDialog({

View File

@ -117,7 +117,7 @@ const StrategyConstraintInputField = ({
multiple multiple
size="small" size="small"
options={options} options={options}
data-test={CONSTRAINT_AUTOCOMPLETE_ID} data-testid={CONSTRAINT_AUTOCOMPLETE_ID}
value={values || []} value={values || []}
getOptionLabel={option => option.label} getOptionLabel={option => option.label}
onBlur={onBlur} onBlur={onBlur}

View File

@ -104,7 +104,7 @@ const FlexibleStrategy = ({
options={stickinessOptions} options={stickinessOptions}
value={stickiness} value={stickiness}
disabled={!editable} disabled={!editable}
data-test={FLEXIBLE_STRATEGY_STICKINESS_ID} data-testid={FLEXIBLE_STRATEGY_STICKINESS_ID}
onChange={e => onChange={e =>
onUpdate('stickiness')(e, e.target.value as number) onUpdate('stickiness')(e, e.target.value as number)
} }
@ -136,7 +136,7 @@ const FlexibleStrategy = ({
value={groupId || ''} value={groupId || ''}
disabled={!editable} disabled={!editable}
onChange={e => onUpdate('groupId')(e, e.target.value)} onChange={e => onUpdate('groupId')(e, e.target.value)}
data-test={FLEXIBLE_STRATEGY_GROUP_ID} data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
/> />
</div> </div>
</div> </div>

View File

@ -101,7 +101,7 @@ const RolloutSlider = ({
getAriaValueText={valuetext} getAriaValueText={valuetext}
aria-labelledby="discrete-slider-always" aria-labelledby="discrete-slider-always"
step={1} step={1}
data-test={ROLLOUT_SLIDER_ID} data-testid={ROLLOUT_SLIDER_ID}
marks={marks} marks={marks}
onChange={onChange} onChange={onChange}
valueLabelDisplay="on" valueLabelDisplay="on"

View File

@ -100,12 +100,12 @@ const StrategyInputList = ({
onChange={onChange} onChange={onChange}
// @ts-expect-error // @ts-expect-error
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
data-test={STRATEGY_INPUT_LIST} data-testid={STRATEGY_INPUT_LIST}
/> />
{/* @ts-expect-error */} {/* @ts-expect-error */}
<Button <Button
onClick={setValue} onClick={setValue}
data-test={ADD_TO_STRATEGY_INPUT_LIST} data-testid={ADD_TO_STRATEGY_INPUT_LIST}
color="secondary" color="secondary"
startIcon={<Add />} startIcon={<Add />}
> >

View File

@ -97,7 +97,7 @@ export const CreateSegment = () => {
name="segment" name="segment"
permission={CREATE_SEGMENT} permission={CREATE_SEGMENT}
disabled={!hasValidConstraints || atSegmentValuesLimit} disabled={!hasValidConstraints || atSegmentValuesLimit}
data-test={SEGMENT_CREATE_BTN_ID} data-testid={SEGMENT_CREATE_BTN_ID}
/> />
</SegmentForm> </SegmentForm>
</FormTemplate> </FormTemplate>

View File

@ -99,7 +99,7 @@ export const EditSegment = () => {
<UpdateButton <UpdateButton
permission={UPDATE_SEGMENT} permission={UPDATE_SEGMENT}
disabled={!hasValidConstraints || atSegmentValuesLimit} disabled={!hasValidConstraints || atSegmentValuesLimit}
data-test={SEGMENT_SAVE_BTN_ID} data-testid={SEGMENT_SAVE_BTN_ID}
/> />
</SegmentForm> </SegmentForm>
</FormTemplate> </FormTemplate>

View File

@ -55,7 +55,7 @@ export const SegmentDeleteConfirm = ({
value={confirmName} value={confirmName}
label="Segment name" label="Segment name"
className={styles.deleteInput} className={styles.deleteInput}
data-test={SEGMENT_DIALOG_NAME_ID} data-testid={SEGMENT_DIALOG_NAME_ID}
/> />
</form> </form>
</Dialogue> </Dialogue>

View File

@ -48,7 +48,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
errorText={errors.name} errorText={errors.name}
autoFocus autoFocus
required required
data-test={SEGMENT_NAME_ID} data-testid={SEGMENT_NAME_ID}
/> />
<p className={styles.inputDescription}> <p className={styles.inputDescription}>
What is the segment description? What is the segment description?
@ -60,7 +60,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
onChange={e => setDescription(e.target.value)} onChange={e => setDescription(e.target.value)}
error={Boolean(errors.description)} error={Boolean(errors.description)}
errorText={errors.description} errorText={errors.description}
data-test={SEGMENT_DESC_ID} data-testid={SEGMENT_DESC_ID}
/> />
</div> </div>
<div className={styles.buttonContainer}> <div className={styles.buttonContainer}>
@ -70,7 +70,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
color="primary" color="primary"
onClick={() => setCurrentStep(2)} onClick={() => setCurrentStep(2)}
disabled={name.length === 0 || Boolean(errors.name)} disabled={name.length === 0 || Boolean(errors.name)}
data-test={SEGMENT_NEXT_BTN_ID} data-testid={SEGMENT_NEXT_BTN_ID}
> >
Next Next
</Button> </Button>

View File

@ -102,7 +102,7 @@ export const SegmentsList = () => {
<PermissionButton <PermissionButton
onClick={() => history.push('/segments/create')} onClick={() => history.push('/segments/create')}
permission={CREATE_SEGMENT} permission={CREATE_SEGMENT}
data-test={NAVIGATE_TO_CREATE_SEGMENT} data-testid={NAVIGATE_TO_CREATE_SEGMENT}
> >
New Segment New Segment
</PermissionButton> </PermissionButton>

View File

@ -83,7 +83,7 @@ export const SegmentListItem = ({
setDelDialog(true); setDelDialog(true);
}} }}
permission={ADMIN} permission={ADMIN}
data-test={`${SEGMENT_DELETE_BTN_ID}_${name}`} data-testid={`${SEGMENT_DELETE_BTN_ID}_${name}`}
> >
<Delete /> <Delete />
</PermissionIconButton> </PermissionIconButton>

View File

@ -73,7 +73,7 @@ export const SplashPageEnvironmentsContent: React.FC<
<IconButton <IconButton
className={styles.closeButton} className={styles.closeButton}
onClick={onClose} onClick={onClose}
data-test={CLOSE_SPLASH} data-testid={CLOSE_SPLASH}
> >
<CloseOutlined titleAccess="Close" /> <CloseOutlined titleAccess="Close" />
</IconButton> </IconButton>

View File

@ -69,7 +69,7 @@ export const StrategiesList = () => {
condition={smallScreen} condition={smallScreen}
show={ show={
<PermissionIconButton <PermissionIconButton
data-test={ADD_NEW_STRATEGY_ID} data-testid={ADD_NEW_STRATEGY_ID}
onClick={() => history.push('/strategies/create')} onClick={() => history.push('/strategies/create')}
permission={CREATE_STRATEGY} permission={CREATE_STRATEGY}
> >
@ -81,7 +81,7 @@ export const StrategiesList = () => {
onClick={() => history.push('/strategies/create')} onClick={() => history.push('/strategies/create')}
color="primary" color="primary"
permission={CREATE_STRATEGY} permission={CREATE_STRATEGY}
data-test={ADD_NEW_STRATEGY_ID} data-testid={ADD_NEW_STRATEGY_ID}
> >
New strategy New strategy
</PermissionButton> </PermissionButton>

View File

@ -42,7 +42,7 @@ exports[`renders correctly with one strategy 1`] = `
> >
<button <button
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary" className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
data-test="ADD_NEW_STRATEGY_ID" data-testid="ADD_NEW_STRATEGY_ID"
disabled={false} disabled={false}
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}
@ -317,7 +317,7 @@ exports[`renders correctly with one strategy without permissions 1`] = `
> >
<button <button
className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary" className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary"
data-test="ADD_NEW_STRATEGY_ID" data-testid="ADD_NEW_STRATEGY_ID"
disabled={false} disabled={false}
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}

View File

@ -0,0 +1,135 @@
import Authentication from 'component/user/Authentication/Authentication';
import { render, screen } from '@testing-library/react';
import {
LOGIN_PASSWORD_ID,
LOGIN_EMAIL_ID,
LOGIN_BUTTON,
AUTH_PAGE_ID,
SSO_LOGIN_BUTTON,
} from 'utils/testIds';
import React from 'react';
import { TestContext } from 'utils/testContext';
import { testServerSetup, testServerRoute } from 'utils/testServer';
const server = testServerSetup();
test('should render password auth', async () => {
testServerRoute(server, '*', {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
path: '/auth/simple/login',
type: 'password',
options: [],
});
render(
<TestContext>
<Authentication redirect="/" />
</TestContext>
);
await screen.findByTestId(AUTH_PAGE_ID);
expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument();
expect(screen.getByTestId(LOGIN_PASSWORD_ID)).toBeInTheDocument();
expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument();
});
test('should not render password auth if defaultHidden is true', async () => {
testServerRoute(server, '*', {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
path: '/auth/simple/login',
type: 'password',
options: [],
});
render(
<TestContext>
<Authentication redirect="/" />
</TestContext>
);
await screen.findByTestId(AUTH_PAGE_ID);
expect(screen.queryByTestId(LOGIN_EMAIL_ID)).not.toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_BUTTON)).not.toBeInTheDocument();
});
test('should render demo auth', async () => {
testServerRoute(server, '*', {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
path: '/auth/demo/login',
type: 'demo',
options: [],
});
render(
<TestContext>
<Authentication redirect="/" />
</TestContext>
);
await screen.findByTestId(AUTH_PAGE_ID);
expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument();
expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument();
});
test('should render email auth', async () => {
testServerRoute(server, '*', {
defaultHidden: false,
message: 'You must sign in in order to use Unleash',
path: '/auth/unsecure/login',
type: 'unsecure',
options: [],
});
render(
<TestContext>
<Authentication redirect="/" />
</TestContext>
);
await screen.findByTestId(AUTH_PAGE_ID);
expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument();
expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument();
});
test('should render Google auth', async () => {
await testSSOAuthOption('google');
});
test('should render OIDC auth', async () => {
await testSSOAuthOption('oidc');
});
test('should render SAML auth', async () => {
await testSSOAuthOption('saml');
});
const testSSOAuthOption = async (authOption: string) => {
const path = `/auth/${authOption}/login`;
const testId = `${SSO_LOGIN_BUTTON}-${authOption}`;
testServerRoute(server, '*', {
defaultHidden: true,
message: 'You must sign in in order to use Unleash',
options: [{ type: authOption, message: '...', path: path }],
path: '/auth/simple/login',
type: 'password',
});
render(
<TestContext>
<Authentication redirect="/" />
</TestContext>
);
const ssoLink = await screen.findByTestId(testId);
expect(ssoLink.getAttribute('href')).toEqual(path);
expect(screen.queryByTestId(LOGIN_EMAIL_ID)).not.toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument();
expect(screen.queryByTestId(LOGIN_BUTTON)).not.toBeInTheDocument();
};

View File

@ -14,16 +14,20 @@ import useQueryParams from 'hooks/useQueryParams';
import ConditionallyRender from 'component/common/ConditionallyRender'; import ConditionallyRender from 'component/common/ConditionallyRender';
import { Alert } from '@material-ui/lab'; import { Alert } from '@material-ui/lab';
import { useAuthDetails } from 'hooks/api/getters/useAuth/useAuthDetails'; import { useAuthDetails } from 'hooks/api/getters/useAuth/useAuthDetails';
import { AUTH_PAGE_ID } from 'utils/testIds';
interface IAuthenticationProps { interface IAuthenticationProps {
redirect: string; redirect: string;
} }
const Authentication = ({ redirect }: IAuthenticationProps) => { const Authentication = ({ redirect }: IAuthenticationProps) => {
const { authDetails } = useAuthDetails(); const { authDetails } = useAuthDetails();
const params = useQueryParams(); const params = useQueryParams();
const error = params.get('errorMsg'); const error = params.get('errorMsg');
if (!authDetails) return null;
if (!authDetails) {
return null;
}
let content; let content;
if (authDetails.type === PASSWORD_TYPE) { if (authDetails.type === PASSWORD_TYPE) {
@ -53,9 +57,10 @@ const Authentication = ({ redirect }: IAuthenticationProps) => {
} else { } else {
content = <AuthenticationCustomComponent authDetails={authDetails} />; content = <AuthenticationCustomComponent authDetails={authDetails} />;
} }
return ( return (
<> <>
<div style={{ maxWidth: '350px' }}> <div style={{ maxWidth: '350px' }} data-testid={AUTH_PAGE_ID}>
<ConditionallyRender <ConditionallyRender
condition={Boolean(error)} condition={Boolean(error)}
show={<Alert severity="error">{error}</Alert>} show={<Alert severity="error">{error}</Alert>}

View File

@ -45,12 +45,12 @@ const DemoAuth = ({ authDetails, redirect }) => {
value={email} value={email}
className={styles.emailField} className={styles.emailField}
onChange={handleChange} onChange={handleChange}
inputProps={{ 'data-test': 'email-input-field' }} inputProps={{ 'data-testid': 'email-input-field' }}
size="small" size="small"
variant="outlined" variant="outlined"
label="Email" label="Email"
name="email" name="email"
data-test={LOGIN_EMAIL_ID} data-testid={LOGIN_EMAIL_ID}
required required
type="email" type="email"
/> />
@ -60,7 +60,7 @@ const DemoAuth = ({ authDetails, redirect }) => {
variant="contained" variant="contained"
color="primary" color="primary"
className={styles.button} className={styles.button}
data-test={LOGIN_BUTTON} data-testid={LOGIN_BUTTON}
> >
Sign in Sign in
</Button> </Button>

View File

@ -0,0 +1,15 @@
import { render, screen } from '@testing-library/react';
import { FORGOTTEN_PASSWORD_FIELD } from 'utils/testIds';
import React from 'react';
import { TestContext } from 'utils/testContext';
import ForgottenPassword from 'component/user/ForgottenPassword/ForgottenPassword';
test('should render password auth', async () => {
render(
<TestContext>
<ForgottenPassword />
</TestContext>
);
await screen.findByTestId(FORGOTTEN_PASSWORD_FIELD);
});

View File

@ -96,7 +96,7 @@ const ForgottenPassword = () => {
placeholder="email" placeholder="email"
type="email" type="email"
data-loading data-loading
data-test={FORGOTTEN_PASSWORD_FIELD} data-testid={FORGOTTEN_PASSWORD_FIELD}
value={email} value={email}
onChange={e => { onChange={e => {
setEmail(e.target.value); setEmail(e.target.value);

View File

@ -109,7 +109,7 @@ const HostedAuth = ({ authDetails, redirect }) => {
helperText={usernameError} helperText={usernameError}
variant="outlined" variant="outlined"
size="small" size="small"
data-test={LOGIN_EMAIL_ID} data-testid={LOGIN_EMAIL_ID}
/> />
<PasswordField <PasswordField
label="Password" label="Password"
@ -118,7 +118,7 @@ const HostedAuth = ({ authDetails, redirect }) => {
value={password} value={password}
error={!!passwordError} error={!!passwordError}
helperText={passwordError} helperText={passwordError}
data-test={LOGIN_PASSWORD_ID} data-testid={LOGIN_PASSWORD_ID}
/> />
<Grid container> <Grid container>
<Button <Button
@ -126,7 +126,7 @@ const HostedAuth = ({ authDetails, redirect }) => {
color="primary" color="primary"
type="submit" type="submit"
className={styles.button} className={styles.button}
data-test={LOGIN_BUTTON} data-testid={LOGIN_BUTTON}
> >
Sign in Sign in
</Button> </Button>

View File

@ -108,7 +108,7 @@ const PasswordAuth = ({ authDetails, redirect }) => {
error={!!usernameError} error={!!usernameError}
helperText={usernameError} helperText={usernameError}
autoComplete="true" autoComplete="true"
data-test={LOGIN_EMAIL_ID} data-testid={LOGIN_EMAIL_ID}
variant="outlined" variant="outlined"
size="small" size="small"
/> />
@ -120,14 +120,14 @@ const PasswordAuth = ({ authDetails, redirect }) => {
error={!!passwordError} error={!!passwordError}
helperText={passwordError} helperText={passwordError}
autoComplete="true" autoComplete="true"
data-test={LOGIN_PASSWORD_ID} data-testid={LOGIN_PASSWORD_ID}
/> />
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
type="submit" type="submit"
style={{ width: '150px', margin: '1rem auto' }} style={{ width: '150px', margin: '1rem auto' }}
data-test={LOGIN_BUTTON} data-testid={LOGIN_BUTTON}
> >
Sign in Sign in
</Button> </Button>

View File

@ -0,0 +1,26 @@
import { render, screen } from '@testing-library/react';
import { INVALID_TOKEN_BUTTON } from 'utils/testIds';
import React from 'react';
import { TestContext } from 'utils/testContext';
import ResetPassword from 'component/user/ResetPassword/ResetPassword';
import { MemoryRouter } from 'react-router-dom';
import { INVALID_TOKEN_ERROR } from 'hooks/api/getters/useResetPassword/useResetPassword';
import { testServerSetup, testServerRoute } from 'utils/testServer';
const server = testServerSetup();
test('should render password auth', async () => {
testServerRoute(server, '/auth/reset/validate', {
name: INVALID_TOKEN_ERROR,
});
render(
<TestContext>
<MemoryRouter initialEntries={['/new-user?token=invalid']}>
<ResetPassword />
</MemoryRouter>
</TestContext>
);
await screen.findByTestId(INVALID_TOKEN_BUTTON);
});

View File

@ -51,14 +51,14 @@ const SimpleAuth = ({ authDetails, redirect }) => {
<TextField <TextField
value={email} value={email}
onChange={handleChange} onChange={handleChange}
inputProps={{ 'data-test': 'email-input-field' }} inputProps={{ 'data-testid': 'email-input-field' }}
size="small" size="small"
variant="outlined" variant="outlined"
label="Email" label="Email"
name="email" name="email"
required required
type="email" type="email"
data-test={LOGIN_EMAIL_ID} data-testid={LOGIN_EMAIL_ID}
/> />
<br /> <br />
@ -68,7 +68,7 @@ const SimpleAuth = ({ authDetails, redirect }) => {
variant="contained" variant="contained"
color="primary" color="primary"
className={styles.button} className={styles.button}
data-test={LOGIN_BUTTON} data-testid={LOGIN_BUTTON}
> >
Sign in Sign in
</Button> </Button>

View File

@ -71,7 +71,7 @@ const UserProfile = ({
<Avatar <Avatar
alt="user image" alt="user image"
src={imageUrl} src={imageUrl}
data-test={HEADER_USER_AVATAR} data-testid={HEADER_USER_AVATAR}
/> />
<KeyboardArrowDownIcon /> <KeyboardArrowDownIcon />
</Button> </Button>

View File

@ -29,7 +29,7 @@ const AuthOptions = ({ options }: IAuthOptionProps) => {
variant="outlined" variant="outlined"
href={o.path} href={o.path}
size="small" size="small"
data-test={`${SSO_LOGIN_BUTTON}-${o.type}`} data-testid={`${SSO_LOGIN_BUTTON}-${o.type}`}
style={{ height: '40px', color: '#000' }} style={{ height: '40px', color: '#000' }}
startIcon={ startIcon={
<ConditionallyRender <ConditionallyRender

View File

@ -27,7 +27,7 @@ const InvalidToken = () => {
color="primary" color="primary"
component={Link} component={Link}
to="forgotten-password" to="forgotten-password"
data-test={INVALID_TOKEN_BUTTON} data-testid={INVALID_TOKEN_BUTTON}
> >
Reset password Reset password
</Button> </Button>

View File

@ -11,7 +11,7 @@ const getFetcher = (token: string) => () => {
}).then(res => res.json()); }).then(res => res.json());
}; };
const INVALID_TOKEN_ERROR = 'InvalidTokenError'; export const INVALID_TOKEN_ERROR = 'InvalidTokenError';
const USED_TOKEN_ERROR = 'UsedTokenError'; const USED_TOKEN_ERROR = 'UsedTokenError';
const useResetPassword = (options: SWRConfiguration = {}) => { const useResetPassword = (options: SWRConfiguration = {}) => {

View File

@ -0,0 +1,15 @@
import { SWRConfig } from 'swr';
import { MemoryRouter } from 'react-router-dom';
import { ThemeProvider } from '@material-ui/core/styles';
import theme from 'themes/mainTheme';
import React from 'react';
export const TestContext: React.FC = ({ children }) => {
return (
<SWRConfig value={{ provider: () => new Map() }}>
<MemoryRouter>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</MemoryRouter>
</SWRConfig>
);
};

View File

@ -48,3 +48,4 @@ export const CLOSE_SPLASH = 'CLOSE_SPLASH';
export const INPUT_ERROR_TEXT = 'INPUT_ERROR_TEXT'; export const INPUT_ERROR_TEXT = 'INPUT_ERROR_TEXT';
export const HEADER_USER_AVATAR = 'HEADER_USER_AVATAR'; export const HEADER_USER_AVATAR = 'HEADER_USER_AVATAR';
export const SIDEBAR_MODAL_ID = 'SIDEBAR_MODAL_ID'; export const SIDEBAR_MODAL_ID = 'SIDEBAR_MODAL_ID';
export const AUTH_PAGE_ID = 'AUTH_PAGE_ID';

View File

@ -0,0 +1,24 @@
import { SetupServerApi, setupServer } from 'msw/node';
import { rest } from 'msw';
export const testServerSetup = (): SetupServerApi => {
const server = setupServer();
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
return server;
};
export const testServerRoute = (
server: SetupServerApi,
path: string,
json: object
) => {
server.use(
rest.get(path, (req, res, ctx) => {
return res(ctx.json(json));
})
);
};

View File

@ -1482,6 +1482,26 @@
prop-types "^15.7.2" prop-types "^15.7.2"
react-is "^16.8.0 || ^17.0.0" react-is "^16.8.0 || ^17.0.0"
"@mswjs/cookies@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-0.2.0.tgz#7ef2b5d7e444498bb27cf57720e61f76a4ce9f23"
integrity sha512-GTKYnIfXVP8GL8HRWrse+ujqDXCLKvu7+JoL6pvZFzS/d2i9pziByoWD69cOe35JNoSrx2DPNqrhUF+vgV3qUA==
dependencies:
"@types/set-cookie-parser" "^2.4.0"
set-cookie-parser "^2.4.6"
"@mswjs/interceptors@^0.15.1":
version "0.15.1"
resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.15.1.tgz#4a0009f56e51bc2cd3176f1507065c7d2f6c0d5e"
integrity sha512-D5B+ZJNlfvBm6ZctAfRBdNJdCHYAe2Ix4My5qfbHV5WH+3lkt3mmsjiWJzEh5ZwGDauzY487TldI275If7DJVw==
dependencies:
"@open-draft/until" "^1.0.3"
"@xmldom/xmldom" "^0.7.5"
debug "^4.3.3"
headers-polyfill "^3.0.4"
outvariant "^1.2.1"
strict-event-emitter "^0.2.0"
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@ -1503,6 +1523,11 @@
"@nodelib/fs.scandir" "2.1.5" "@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0" fastq "^1.6.0"
"@open-draft/until@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca"
integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3": "@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
version "0.5.5" version "0.5.5"
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca"
@ -1848,6 +1873,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/cookie@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
"@types/debounce@1.2.1": "@types/debounce@1.2.1":
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.2.1.tgz#79b65710bc8b6d44094d286aecf38e44f9627852" resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.2.1.tgz#79b65710bc8b6d44094d286aecf38e44f9627852"
@ -1962,6 +1992,11 @@
jest-matcher-utils "^27.0.0" jest-matcher-utils "^27.0.0"
pretty-format "^27.0.0" pretty-format "^27.0.0"
"@types/js-levenshtein@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5"
integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.11" version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@ -2141,6 +2176,13 @@
"@types/mime" "^1" "@types/mime" "^1"
"@types/node" "*" "@types/node" "*"
"@types/set-cookie-parser@^2.4.0":
version "2.4.2"
resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz#b6a955219b54151bfebd4521170723df5e13caad"
integrity sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==
dependencies:
"@types/node" "*"
"@types/sinonjs__fake-timers@8.1.1": "@types/sinonjs__fake-timers@8.1.1":
version "8.1.1" version "8.1.1"
resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3"
@ -2409,6 +2451,11 @@
"@webassemblyjs/ast" "1.11.1" "@webassemblyjs/ast" "1.11.1"
"@xtuc/long" "4.2.2" "@xtuc/long" "4.2.2"
"@xmldom/xmldom@^0.7.5":
version "0.7.5"
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d"
integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==
"@xtuc/ieee754@^1.2.0": "@xtuc/ieee754@^1.2.0":
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@ -2950,6 +2997,15 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
blob-util@^2.0.2: blob-util@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
@ -3039,7 +3095,7 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^5.6.0: buffer@^5.5.0, buffer@^5.6.0:
version "5.7.1" version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
@ -3128,6 +3184,14 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
chalk@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^2.0.0, chalk@^2.4.1: chalk@^2.0.0, chalk@^2.4.1:
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@ -3145,7 +3209,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -3168,6 +3232,11 @@ charcodes@^0.2.0:
resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4"
integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chart.js@3.7.1: chart.js@3.7.1:
version "3.7.1" version "3.7.1"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.7.1.tgz#0516f690c6a8680c6c707e31a4c1807a6f400ada" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.7.1.tgz#0516f690c6a8680c6c707e31a4c1807a6f400ada"
@ -3242,6 +3311,11 @@ cli-cursor@^3.1.0:
dependencies: dependencies:
restore-cursor "^3.1.0" restore-cursor "^3.1.0"
cli-spinners@^2.5.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d"
integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==
cli-table3@~0.6.1: cli-table3@~0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8"
@ -3259,6 +3333,11 @@ cli-truncate@^2.1.0:
slice-ansi "^3.0.0" slice-ansi "^3.0.0"
string-width "^4.2.0" string-width "^4.2.0"
cli-width@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
cliui@^7.0.2: cliui@^7.0.2:
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@ -3268,6 +3347,11 @@ cliui@^7.0.2:
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi "^7.0.0" wrap-ansi "^7.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
clsx@^1.0.4: clsx@^1.0.4:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
@ -3432,7 +3516,7 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
cookie@0.4.2: cookie@0.4.2, cookie@^0.4.2:
version "0.4.2" version "0.4.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
@ -3816,7 +3900,7 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3:
version "4.3.4" version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@ -3867,6 +3951,13 @@ default-gateway@^6.0.3:
dependencies: dependencies:
execa "^5.0.0" execa "^5.0.0"
defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
dependencies:
clone "^1.0.2"
define-lazy-prop@^2.0.0: define-lazy-prop@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
@ -4520,7 +4611,7 @@ eventemitter3@^4.0.0:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
events@^3.2.0: events@^3.2.0, events@^3.3.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@ -4618,6 +4709,15 @@ extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
dependencies:
chardet "^0.7.0"
iconv-lite "^0.4.24"
tmp "^0.0.33"
extract-zip@2.0.1: extract-zip@2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
@ -4698,7 +4798,7 @@ fd-slicer@~1.1.0:
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
figures@^3.2.0: figures@^3.0.0, figures@^3.2.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
@ -5056,6 +5156,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4,
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
graphql@^16.3.0:
version "16.3.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
gzip-size@^6.0.0: gzip-size@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@ -5112,6 +5217,11 @@ he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
headers-polyfill@^3.0.4:
version "3.0.7"
resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.7.tgz#725c4f591e6748f46b036197eae102c92b959ff4"
integrity sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w==
history@^4.9.0: history@^4.9.0:
version "4.10.1" version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
@ -5289,7 +5399,7 @@ hyphenate-style-name@^1.0.3:
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
iconv-lite@0.4.24: iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -5394,6 +5504,26 @@ ini@^1.3.5:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
inquirer@^8.2.0:
version "8.2.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.2.tgz#1310517a87a0814d25336c78a20b44c3d9b7629d"
integrity sha512-pG7I/si6K/0X7p1qU+rfWnpTE1UIkTONN1wxtzh0d+dHXtT/JG6qBgLxoyHVsQa8cFABxAPh0pD6uUUHiAoaow==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
cli-cursor "^3.1.0"
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.21"
mute-stream "0.0.8"
ora "^5.4.1"
run-async "^2.4.0"
rxjs "^7.5.5"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
internal-slot@^1.0.3: internal-slot@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
@ -5506,6 +5636,11 @@ is-installed-globally@~0.4.0:
global-dirs "^3.0.0" global-dirs "^3.0.0"
is-path-inside "^3.0.2" is-path-inside "^3.0.2"
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-module@^1.0.0: is-module@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
@ -5516,6 +5651,11 @@ is-negative-zero@^2.0.2:
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
is-node-process@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23"
integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==
is-number-object@^1.0.4: is-number-object@^1.0.4:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
@ -6115,6 +6255,11 @@ jest@^27.4.3:
import-local "^3.0.2" import-local "^3.0.2"
jest-cli "^27.5.1" jest-cli "^27.5.1"
js-levenshtein@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -6498,7 +6643,7 @@ lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.0.0: log-symbols@^4.0.0, log-symbols@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
@ -6535,11 +6680,6 @@ lru-cache@^7.4.0:
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252"
integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw== integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==
lru-cache@^7.4.0:
version "7.7.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252"
integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==
lz-string@^1.4.4: lz-string@^1.4.4:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
@ -6704,6 +6844,31 @@ ms@2.1.3, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
msw@^0.39.2:
version "0.39.2"
resolved "https://registry.yarnpkg.com/msw/-/msw-0.39.2.tgz#832e9274db62c43cb79854d5a69dce031c700de8"
integrity sha512-ju/HpqQpE4/qCxZ23t5Gaau0KREn4QuFzdG28nP1EpidMrymMJuIvNd32+2uGTGG031PMwrC41YW7vCxHOwyHA==
dependencies:
"@mswjs/cookies" "^0.2.0"
"@mswjs/interceptors" "^0.15.1"
"@open-draft/until" "^1.0.3"
"@types/cookie" "^0.4.1"
"@types/js-levenshtein" "^1.1.1"
chalk "4.1.1"
chokidar "^3.4.2"
cookie "^0.4.2"
graphql "^16.3.0"
headers-polyfill "^3.0.4"
inquirer "^8.2.0"
is-node-process "^1.0.1"
js-levenshtein "^1.1.6"
node-fetch "^2.6.7"
path-to-regexp "^6.2.0"
statuses "^2.0.0"
strict-event-emitter "^0.2.0"
type-fest "^1.2.2"
yargs "^17.3.1"
multicast-dns@^7.2.4: multicast-dns@^7.2.4:
version "7.2.4" version "7.2.4"
resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.4.tgz#cf0b115c31e922aeb20b64e6556cbeb34cf0dd19" resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.4.tgz#cf0b115c31e922aeb20b64e6556cbeb34cf0dd19"
@ -6712,6 +6877,11 @@ multicast-dns@^7.2.4:
dns-packet "^5.2.2" dns-packet "^5.2.2"
thunky "^1.0.2" thunky "^1.0.2"
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
nanoid@^3.3.1: nanoid@^3.3.1:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
@ -6740,6 +6910,13 @@ no-case@^3.0.4:
lower-case "^2.0.2" lower-case "^2.0.2"
tslib "^2.0.3" tslib "^2.0.3"
node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-forge@^1: node-forge@^1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
@ -6934,11 +7111,36 @@ optionator@^0.9.1:
type-check "^0.4.0" type-check "^0.4.0"
word-wrap "^1.2.3" word-wrap "^1.2.3"
ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
dependencies:
bl "^4.1.0"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-spinners "^2.5.0"
is-interactive "^1.0.0"
is-unicode-supported "^0.1.0"
log-symbols "^4.1.0"
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
ospath@^1.2.2: ospath@^1.2.2:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=
outvariant@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.3.0.tgz#c39723b1d2cba729c930b74bf962317a81b9b1c9"
integrity sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==
p-limit@^1.1.0: p-limit@^1.1.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
@ -7093,6 +7295,11 @@ path-to-regexp@^1.7.0:
dependencies: dependencies:
isarray "0.0.1" isarray "0.0.1"
path-to-regexp@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38"
integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==
path-type@^4.0.0: path-type@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@ -8097,7 +8304,7 @@ readable-stream@^2.0.1:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^3.0.6: readable-stream@^3.0.6, readable-stream@^3.4.0:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@ -8341,6 +8548,11 @@ rollup@^2.43.1:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
run-parallel@^1.1.9: run-parallel@^1.1.9:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@ -8348,7 +8560,7 @@ run-parallel@^1.1.9:
dependencies: dependencies:
queue-microtask "^1.2.2" queue-microtask "^1.2.2"
rxjs@^7.5.1: rxjs@^7.5.1, rxjs@^7.5.5:
version "7.5.5" version "7.5.5"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==
@ -8466,7 +8678,7 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
semver@7.3.6: semver@7.3.6, semver@^7.3.2, semver@^7.3.5:
version "7.3.6" version "7.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b"
integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w== integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==
@ -8478,13 +8690,6 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.3.2, semver@^7.3.5:
version "7.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b"
integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==
dependencies:
lru-cache "^7.4.0"
send@0.17.2: send@0.17.2:
version "0.17.2" version "0.17.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820"
@ -8541,6 +8746,11 @@ serve-static@1.14.2:
parseurl "~1.3.3" parseurl "~1.3.3"
send "0.17.2" send "0.17.2"
set-cookie-parser@^2.4.6:
version "2.4.8"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2"
integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==
setprototypeof@1.1.0: setprototypeof@1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
@ -8751,6 +8961,18 @@ stackframe@^1.1.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
statuses@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
strict-event-emitter@^0.2.0:
version "0.2.4"
resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz#365714f0c95f059db31064ca745d5b33e5b30f6e"
integrity sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ==
dependencies:
events "^3.3.0"
string-length@^4.0.1: string-length@^4.0.1:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
@ -8772,7 +8994,7 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
string-width@^4.1.0, string-width@^4.2.0: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -9079,7 +9301,7 @@ throttleit@^1.0.0:
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=
through@^2.3.8: through@^2.3.6, through@^2.3.8:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@ -9099,6 +9321,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies:
os-tmpdir "~1.0.2"
tmp@~0.2.1: tmp@~0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
@ -9164,6 +9393,11 @@ tr46@^2.1.0:
dependencies: dependencies:
punycode "^2.1.1" punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
tryer@^1.0.1: tryer@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
@ -9242,6 +9476,11 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
type-fest@^1.2.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
type-is@~1.6.18: type-is@~1.6.18:
version "1.6.18" version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
@ -9438,6 +9677,18 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies: dependencies:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
dependencies:
defaults "^1.0.3"
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
webidl-conversions@^4.0.2: webidl-conversions@^4.0.2:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@ -9589,6 +9840,14 @@ whatwg-mimetype@^2.3.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
whatwg-url@^7.0.0: whatwg-url@^7.0.0:
version "7.1.0" version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
@ -9879,6 +10138,11 @@ yargs-parser@^20.2.2:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs-parser@^21.0.0:
version "21.0.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==
yargs@^16.2.0: yargs@^16.2.0:
version "16.2.0" version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
@ -9892,6 +10156,19 @@ yargs@^16.2.0:
y18n "^5.0.5" y18n "^5.0.5"
yargs-parser "^20.2.2" yargs-parser "^20.2.2"
yargs@^17.3.1:
version "17.4.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.0.tgz#9fc9efc96bd3aa2c1240446af28499f0e7593d00"
integrity sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.3"
y18n "^5.0.5"
yargs-parser "^21.0.0"
yauzl@^2.10.0: yauzl@^2.10.0:
version "2.10.0" version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"