Skip to content

Commit 8e80934

Browse files
author
Greg Trihus
committed
TT-6814-17, TT-6428 Add Phrase Back Translation mobile layout
- Introduced Cypress component testing takeaways to guide best practices in testing setups and assertions. - Added Jest testing takeaways for unit tests, emphasizing mocking strategies and edge case coverage. - Refactored MediaRecord, WSAudioPlayer, and related components to improve props handling and mobile responsiveness. - Updated UserMenu and PlanTabs components to utilize new mobile utility functions for better layout management.
1 parent 5508aed commit 8e80934

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3976
-492
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
description: Cypress component test takeaways for this repo
3+
alwaysApply: true
4+
---
5+
6+
# Cypress Component Testing Takeaways
7+
8+
- Avoid stubbing ESM imports in Cypress CT; prefer data-driven setup via providers.
9+
- Build the full provider stack: `GlobalProvider`, Redux store, `OrbitContext`,
10+
and any feature contexts (e.g. `PassageDetailContext`, `UnsavedContext`).
11+
- For permission logic (`useStepPermissions`), drive outcomes with real mock records and relationships.
12+
- Localization selectors need `LocalizedStrings` in the correct `strings` slice keys.
13+
- Use stable DOM selectors (ids/data-cy) for assertions.
14+
- When testing navigation that uses `usePassageNavigate`, include a `MemoryRouter`
15+
- `Routes` and stub `UnsavedContext.checkSavedFn` to run immediately.
16+
- `nextPasId`/`prevPasId` depend on `section.relationships.passages` and
17+
`memory` records; empty relationships mean no neighbors.
18+
- `WorkflowStepsMobile` renders SVG stages (no visible text nodes). Assert on
19+
structure (`svg`, `svg g`) or wrapper labels, not `cy.contains` on step names.
20+
- `WorkflowStepsMobile` depends on `workflow`/`currentstep` from context; keep
21+
defaults intact when overriding to avoid empty steps.
22+
- For `WorkflowStepsMobile`, set viewport and dispatch a `resize` after mount so
23+
the width-driven step list is computed.
24+
- When testing busy/recording state, assert via `setCurrentStep` calls and snack
25+
messages rather than DOM class changes.
26+
- Pagination needs enough steps and a small viewport to expose `prev`/`next`.
27+
- Run the component spec and iterate on failures:
28+
- `cd src\renderer`
29+
- `npm run cy:run-ct -- --spec=**/YourComponent.cy.tsx`
30+
31+
## Example: Minimal Strings Slice
32+
33+
```ts
34+
const mockStringsReducer = () => ({
35+
loaded: true,
36+
lang: 'en',
37+
passageDetailStepComplete: new LocalizedStrings({
38+
en: { title: 'Complete' },
39+
}),
40+
});
41+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
description: Jest testing takeaways for this repo
3+
alwaysApply: true
4+
---
5+
6+
# Jest Testing Takeaways
7+
8+
- Favor unit tests for non-React modules (pure functions, CRUD helpers).
9+
- Mock Orbit helpers (`related`, `findRecord`) and other dependencies; keep test data minimal.
10+
- Cover edge cases: missing relationships, missing current id, filtering, wrap-around.
11+
- Prefer deterministic sorting in tests (explicit `sequencenum`).
12+
- Use `--runInBand --watchAll=false` to avoid hanging runs in CI/automation.
13+
14+
## Running a New Jest Test Module
15+
16+
Run Jest from `src/renderer` (required for this repo).
17+
18+
```bash
19+
cd src/renderer
20+
npm test -- <moduleName> --runInBand --watchAll=false
21+
```

localization/TranscriberAdmin-en-1.2.xliff

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,56 @@
51695169
<context context-type="sourcefile">MediaUpload.tsx</context>
51705170
</context-group>
51715171
</trans-unit>
5172+
<trans-unit id="mobile.addSegment">
5173+
<source>Add segment boundary</source>
5174+
<target/>
5175+
<context-group>
5176+
<context context-type="sourcefile">SegmentControlIsMobile.tsx</context>
5177+
</context-group>
5178+
</trans-unit>
5179+
<trans-unit id="mobile.next">
5180+
<source>Next</source>
5181+
<target/>
5182+
<context-group>
5183+
<context context-type="sourcefile">PassageDetailMobileFooter.tsx</context>
5184+
</context-group>
5185+
</trans-unit>
5186+
<trans-unit id="mobile.previous">
5187+
<source>Previous</source>
5188+
<target/>
5189+
<context-group>
5190+
<context context-type="sourcefile">PassageDetailMobileFooter.tsx</context>
5191+
</context-group>
5192+
</trans-unit>
5193+
<trans-unit id="mobile.removeSegment">
5194+
<source>Remove next segment boundary</source>
5195+
<target/>
5196+
<context-group>
5197+
<context context-type="sourcefile">SegmentControlIsMobile.tsx</context>
5198+
</context-group>
5199+
</trans-unit>
5200+
<trans-unit id="mobile.resetBT">
5201+
<source>Reset back translation</source>
5202+
<target/>
5203+
<context-group>
5204+
<context context-type="sourcefile">SegmentControlIsMobile.tsx</context>
5205+
</context-group>
5206+
</trans-unit>
5207+
<trans-unit id="mobile.restoreBoundaries">
5208+
<source>Restore original segment boundaries</source>
5209+
<target/>
5210+
<context-group>
5211+
<context context-type="sourcefile">SegmentControlIsMobile.tsx</context>
5212+
</context-group>
5213+
</trans-unit>
5214+
<trans-unit id="mobile.segment">
5215+
<source>Segment: {0}</source>
5216+
<target/>
5217+
<context-group>
5218+
<context context-type="sourcefile">SegmentControlIsMobile.tsx</context>
5219+
</context-group>
5220+
</trans-unit>
5221+
51725222
<trans-unit id="newProject.audioProduct">
51735223
<source>Audio Product</source>
51745224
<target/>
@@ -7438,6 +7488,27 @@
74387488
<context context-type="sourcefile">ResourceOverview.tsx</context>
74397489
</context-group>
74407490
</trans-unit>
7491+
<trans-unit id="recordButton.record">
7492+
<source>RECORD</source>
7493+
<target/>
7494+
<context-group>
7495+
<context context-type="sourcefile">RecordButton.tsx</context>
7496+
</context-group>
7497+
</trans-unit>
7498+
<trans-unit id="recordButton.rerecord">
7499+
<source>RERECORD</source>
7500+
<target/>
7501+
<context-group>
7502+
<context context-type="sourcefile">RecordButton.tsx</context>
7503+
</context-group>
7504+
</trans-unit>
7505+
<trans-unit id="recordButton.resume">
7506+
<source>RESUME</source>
7507+
<target/>
7508+
<context-group>
7509+
<context context-type="sourcefile">RecordButton.tsx</context>
7510+
</context-group>
7511+
</trans-unit>
74417512
<trans-unit id="recordStepSettings.custom">
74427513
<source>Custom</source>
74437514
<target/>
@@ -10968,6 +11039,13 @@
1096811039
<context context-type="sourcefile">wsAudioPlayer.tsx</context>
1096911040
</context-group>
1097011041
</trans-unit>
11042+
<trans-unit id="wsAudioPlayer.reset">
11043+
<source>Reset</source>
11044+
<target/>
11045+
<context-group>
11046+
<context context-type="sourcefile">wsAudioPlayer.tsx</context>
11047+
</context-group>
11048+
</trans-unit>
1097111049
<trans-unit id="wsAudioPlayer.resume">
1097211050
<source>Resume</source>
1097311051
<target/>

localization/TranscriberAdmin-en.xlf

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4432,6 +4432,48 @@
44324432
<target/>
44334433
</segment>
44344434
</unit>
4435+
<unit id="mobile.addSegment">
4436+
<segment>
4437+
<source>Add segment boundary</source>
4438+
<target/>
4439+
</segment>
4440+
</unit>
4441+
<unit id="mobile.next">
4442+
<segment>
4443+
<source>Next</source>
4444+
<target/>
4445+
</segment>
4446+
</unit>
4447+
<unit id="mobile.previous">
4448+
<segment>
4449+
<source>Previous</source>
4450+
<target/>
4451+
</segment>
4452+
</unit>
4453+
<unit id="mobile.removeSegment">
4454+
<segment>
4455+
<source>Remove next segment boundary</source>
4456+
<target/>
4457+
</segment>
4458+
</unit>
4459+
<unit id="mobile.resetBT">
4460+
<segment>
4461+
<source>Reset back translation</source>
4462+
<target/>
4463+
</segment>
4464+
</unit>
4465+
<unit id="mobile.restoreBoundaries">
4466+
<segment>
4467+
<source>Restore original segment boundaries</source>
4468+
<target/>
4469+
</segment>
4470+
</unit>
4471+
<unit id="mobile.segment">
4472+
<segment>
4473+
<source>Segment: {0}</source>
4474+
<target/>
4475+
</segment>
4476+
</unit>
44354477
<unit id="newProject.audioProduct">
44364478
<segment>
44374479
<source>Audio Product</source>
@@ -6376,6 +6418,24 @@
63766418
<target/>
63776419
</segment>
63786420
</unit>
6421+
<unit id="recordButton.record">
6422+
<segment>
6423+
<source>RECORD</source>
6424+
<target/>
6425+
</segment>
6426+
</unit>
6427+
<unit id="recordButton.rerecord">
6428+
<segment>
6429+
<source>RERECORD</source>
6430+
<target/>
6431+
</segment>
6432+
</unit>
6433+
<unit id="recordButton.resume">
6434+
<segment>
6435+
<source>RESUME</source>
6436+
<target/>
6437+
</segment>
6438+
</unit>
63796439
<unit id="recordStepSettings.custom">
63806440
<segment>
63816441
<source>Custom</source>
@@ -9400,6 +9460,12 @@
94009460
<target/>
94019461
</segment>
94029462
</unit>
9463+
<unit id="wsAudioPlayer.reset">
9464+
<segment>
9465+
<source>Reset</source>
9466+
<target/>
9467+
</segment>
9468+
</unit>
94039469
<unit id="wsAudioPlayer.resume">
94049470
<segment>
94059471
<source>Resume</source>

src/renderer/public/localization/strings30ef9214.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

src/renderer/public/localization/stringsce223310.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/renderer/src/components/App/AppHead.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
LinearProgress,
1212
Tooltip,
1313
Box,
14-
useTheme,
15-
useMediaQuery,
1614
} from '@mui/material';
1715
import HomeIcon from '@mui/icons-material/Home';
1816
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
@@ -35,6 +33,7 @@ import {
3533
exitApp,
3634
useMyNavigate,
3735
useWaitForRemoteQueue,
36+
useMobile,
3837
} from '../../utils';
3938
import { withBucket } from '../../hoc/withBucket';
4039
import { usePlan } from '../../crud';
@@ -48,6 +47,7 @@ import { useHome } from '../../utils/useHome';
4847
import { ApmLogo } from '../../control/ApmLogo';
4948
import { OrgHead } from './OrgHead';
5049
import { HeadStatus } from './HeadStatus';
50+
import MobileDetailTitle from './MobileDetailTitle';
5151

5252
const twoIcon = { minWidth: `calc(${48 * 2}px)` } as React.CSSProperties;
5353
const threeIcon = { minWidth: `calc(${48 * 3}px)` } as React.CSSProperties;
@@ -115,8 +115,7 @@ export const AppHead = (props: IProps) => {
115115
const orbitErrorMsg = useSelector((state: IState) => state.orbit.message);
116116
const { pathname } = useLocation();
117117
const navigate = useMyNavigate();
118-
const theme = useTheme();
119-
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
118+
const { isMobileView, isMobileWidth } = useMobile();
120119
const [home] = useGlobal('home'); //verified this is not used in a function 2/18/25
121120
const [orgRole] = useGlobal('orgRole'); //verified this is not used in a function 2/18/25
122121
const [errorReporter] = useGlobal('errorReporter');
@@ -149,7 +148,6 @@ export const AppHead = (props: IProps) => {
149148
const [showTerms, setShowTerms] = useState('');
150149
const waitForRemoteQueue = useWaitForRemoteQueue();
151150
const waitForDataChangesQueue = useWaitForRemoteQueue('datachanges');
152-
const [mobileView] = useGlobal('mobileView');
153151

154152
// eslint-disable-next-line react-hooks/exhaustive-deps
155153
const saving = useMemo(() => anySaving(), [toolsChanged]);
@@ -344,7 +342,7 @@ export const AppHead = (props: IProps) => {
344342
if (view === 'Terms') navigate('/terms');
345343
if (view === 'Privacy') navigate('/privacy');
346344

347-
return !mobileView && !isMobileWidth ? (
345+
return !isMobileView && !isMobileWidth ? (
348346
<AppBar
349347
position="fixed"
350348
sx={{ width: '100%', display: 'flex' }}
@@ -417,11 +415,13 @@ export const AppHead = (props: IProps) => {
417415
<ApmLogo sx={{ width: '24px', height: '24px' }} />
418416
</IconButton>
419417
) : (
420-
<IconButton onClick={() => navigate(planUrl || '/team')}>
418+
<IconButton
419+
onClick={() => checkSavedFn(() => navigate(planUrl || '/team'))}
420+
>
421421
<ArrowBackIcon sx={{ width: '24px', height: '24px' }} />
422422
</IconButton>
423423
)}
424-
<OrgHead />
424+
{isDetail ? <MobileDetailTitle /> : <OrgHead />}
425425
<GrowingSpacer />
426426
{!isMobileWidth && (
427427
<HeadStatus

0 commit comments

Comments
 (0)