generated from Tinkoff/angular-open-source-starter
-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react):
elementPredicate
can accept asynchronous predicate (#502)
- Loading branch information
1 parent
58531ae
commit 4bbf758
Showing
12 changed files
with
369 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
export type MaskitoElementPredicate = ( | ||
element: HTMLElement, | ||
) => HTMLInputElement | HTMLTextAreaElement; | ||
) => HTMLInputElement | HTMLTextAreaElement; // TODO: add `Promise<HTMLInputElement | HTMLTextAreaElement>` | ||
|
||
// TODO: delete in v2.0 | ||
export type MaskitoElementPredicateAsync = ( | ||
element: HTMLElement, | ||
) => Promise<HTMLInputElement | HTMLTextAreaElement>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,7 @@ | ||
// *********************************************** | ||
// This example commands.js shows you how to | ||
// create various custom commands and overwrite | ||
// existing commands. | ||
// | ||
// For more comprehensive examples of custom | ||
// commands please read more here: | ||
// https://on.cypress.io/custom-commands | ||
// *********************************************** | ||
// | ||
// | ||
// -- This is a parent command -- | ||
// Cypress.Commands.add('login', (email, password) => { ... }) | ||
// | ||
// | ||
// -- This is a child command -- | ||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) | ||
// | ||
// | ||
// -- This is a dual command -- | ||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) | ||
// | ||
// | ||
// -- This will overwrite an existing command -- | ||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) | ||
import {smartTick} from './commands/smart-tick'; | ||
|
||
/* eslint-disable unicorn/no-empty-file */ | ||
Cypress.Commands.add( | ||
'smartTick', | ||
{prevSubject: ['optional', 'element', 'window', 'document']}, | ||
smartTick, | ||
); |
26 changes: 26 additions & 0 deletions
26
projects/demo-integrations/cypress/support/commands/smart-tick.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
export function smartTick( | ||
$subject: Cypress.PrevSubjectMap<void>[Cypress.PrevSubject], | ||
durationMs: number, // ms | ||
frequencyMs = 100, // ms | ||
): Cypress.Chainable<unknown> { | ||
const iterations = Math.ceil(durationMs / frequencyMs); | ||
const lastIterationMs = durationMs % frequencyMs || frequencyMs; | ||
|
||
for (let i = 1; i <= iterations; i++) { | ||
cy.tick(i === iterations ? lastIterationMs : frequencyMs, {log: false}); | ||
cy.wait(0, {log: false}); // allow React hooks to process | ||
} | ||
|
||
Cypress.log({ | ||
displayName: 'smartTick', | ||
message: `${durationMs}ms`, | ||
consoleProps() { | ||
return { | ||
durationMs, | ||
frequencyMs, | ||
}; | ||
}, | ||
}); | ||
|
||
return cy.wrap($subject, {log: false}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
projects/demo/src/pages/cypress/examples/5-react-async-predicate/angular-wrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import {isPlatformBrowser} from '@angular/common'; | ||
import {ChangeDetectionStrategy, Component, ElementRef, Inject, PLATFORM_ID} from '@angular/core'; | ||
import {createRoot} from 'react-dom/client'; | ||
|
||
import {App} from './react-app'; | ||
|
||
@Component({ | ||
selector: 'test-doc-example-5', | ||
template: '', | ||
changeDetection: ChangeDetectionStrategy.OnPush, | ||
}) | ||
export class TestDocExample5 { | ||
constructor(elementRef: ElementRef, @Inject(PLATFORM_ID) platformId: Record<string, unknown>) { | ||
if (isPlatformBrowser(platformId)) { | ||
createRoot(elementRef.nativeElement).render(<App />); | ||
} | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
projects/demo/src/pages/cypress/examples/5-react-async-predicate/react-app.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// @ts-nocheck React & Vue Global JSX Types Conflicts | ||
// TODO: Check if it still required after upgrade Vue to 3.4 (https://github.com/vuejs/core/pull/7958) | ||
import type {MaskitoElementPredicateAsync} from '@maskito/core'; | ||
import {MaskitoElementPredicate} from '@maskito/core'; | ||
import {maskitoTimeOptionsGenerator} from '@maskito/kit'; | ||
import {useMaskito} from '@maskito/react'; | ||
import {forwardRef, useEffect, useState} from 'react'; | ||
|
||
const options = maskitoTimeOptionsGenerator({ | ||
mode: 'HH:MM', | ||
}); | ||
|
||
const correctPredicate: MaskitoElementPredicate = host => host.querySelector('.real-input')!; | ||
const wrongPredicate: MaskitoElementPredicate = host => host.querySelector('input')!; | ||
|
||
const longCorrectPredicate: MaskitoElementPredicateAsync = host => | ||
new Promise(resolve => { | ||
setTimeout(() => { | ||
resolve(correctPredicate(host)); | ||
}, 2_000); | ||
}); | ||
|
||
const longInvalidPredicate: MaskitoElementPredicateAsync = host => | ||
new Promise(resolve => { | ||
setTimeout(() => resolve(wrongPredicate(host)), 7_000); | ||
}); | ||
|
||
const fastValidPredicate: MaskitoElementPredicateAsync = host => | ||
new Promise(resolve => { | ||
setTimeout(() => resolve(correctPredicate(host)), 500); | ||
}); | ||
|
||
const hiddenInputStyles = { | ||
display: 'none', | ||
}; | ||
|
||
export const AwesomeInput = forwardRef<HTMLInputElement>((props, ref) => ( | ||
<div ref={ref}> | ||
<input style={hiddenInputStyles} /> | ||
<input | ||
className="real-input" | ||
{...props} | ||
/> | ||
<input style={hiddenInputStyles} /> | ||
</div> | ||
)); | ||
|
||
export const App = () => { | ||
const [useCorrectPredicate, setUseCorrectPredicate] = useState(false); | ||
const inputRef2sec = useMaskito({options, elementPredicate: longCorrectPredicate}); | ||
const inputRefRaceCondition = useMaskito({ | ||
options, | ||
elementPredicate: useCorrectPredicate ? fastValidPredicate : longInvalidPredicate, | ||
}); | ||
|
||
useEffect(() => { | ||
setTimeout(() => { | ||
setUseCorrectPredicate(true); | ||
}, 2_000); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<AwesomeInput | ||
ref={inputRef2sec} | ||
id="async-predicate-2s-resolves" | ||
placeholder="Async predicate (2s)" | ||
/> | ||
|
||
<AwesomeInput | ||
ref={inputRefRaceCondition} | ||
id="race-condition-check" | ||
placeholder="Race condition check" | ||
/> | ||
</> | ||
); | ||
}; |
Oops, something went wrong.