From 6da0fc834d07c9fafdfcb11748a82e8373da918b Mon Sep 17 00:00:00 2001 From: Aaron Luna Date: Sun, 28 Jan 2024 07:09:26 -0800 Subject: [PATCH 1/5] refactor(svelte-base64): :recycle: refactor app context initialization --- .../AlgorithmDemo/AlgorithmDemo.svelte | 6 +-- .../Buttons/CopyEncodedText.svelte | 4 +- .../Buttons/OpenHelpDocsButton.svelte | 4 +- .../AlgorithmDemo/DemoIntro/DemoIntro.svelte | 5 +- .../DemoResults/DemoResults.svelte | 4 +- .../DemoResults/InputByte.svelte | 4 +- .../DemoResults/InputChunk.svelte | 4 +- .../DemoResults/OutputByte.svelte | 4 +- .../DemoResults/OutputBytePlaceholder.svelte | 4 +- .../DemoResults/OutputChunk.svelte | 4 +- .../AlgorithmDemo/DemoText/DemoText.svelte | 4 +- .../DemoText/Utf8/EncodedBytesForChar.svelte | 4 +- .../DemoText/Utf8/Utf8EncodedBytes.svelte | 4 +- .../AlgorithmDemo/FinalResults.svelte | 4 +- .../HelpDocs/HelpDocsModal.svelte | 4 +- .../AlgorithmDemo/InputForm/InputForm.svelte | 4 +- .../NavButtons/GoToLastStepButton.svelte | 4 +- .../NavButtons/GoToNextStepButton.svelte | 4 +- .../InputForm/NavButtons/NavButton.svelte | 5 +- .../InputForm/NavButtons/NavButtons.svelte | 4 +- .../NavButtons/StartAutoPlayButton.svelte | 4 +- .../AlgorithmDemo/LookupTables.svelte | 3 +- .../components/AlgorithmDemo/MainForm.svelte | 10 +--- .../InputBase64EncodingRadioButtons.svelte | 6 ++- .../lib/components/InputForm/InputForm.svelte | 8 ++- .../InputStringEncodingRadioButtons.svelte | 7 ++- .../OutputBase64EncodingRadioButtons.svelte | 7 ++- .../src/lib/components/RadioButtons.svelte | 7 ++- .../components/Results/InputResults.svelte | 9 +++- .../Results/LookupTables/LookupTables.svelte | 9 +++- .../components/Results/OutputResults.svelte | 9 +++- .../Visualization/EncodedChunk.svelte | 10 ++-- .../Visualization/Visualization.svelte | 9 +++- apps/svelte-base64/src/lib/stores/app.ts | 41 +++++++------- apps/svelte-base64/src/lib/stores/context.ts | 53 ++++++++++++++----- .../svelte-base64/src/lib/stores/demoState.ts | 16 +++--- .../svelte-base64/src/lib/stores/pageWidth.ts | 22 -------- apps/svelte-base64/src/lib/stores/state.ts | 6 +-- apps/svelte-base64/src/routes/+page.svelte | 4 +- .../src/routes/simple/+page.svelte | 7 ++- 40 files changed, 191 insertions(+), 140 deletions(-) delete mode 100644 apps/svelte-base64/src/lib/stores/pageWidth.ts diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte index 040a04d2..aa8823af 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte @@ -10,14 +10,12 @@ import FormTitle from '$lib/components/FormTitle.svelte'; import { defaultEncoderInput } from '$lib/constants'; import { alert } from '$lib/stores/alert'; - import { getAppContext } from '$lib/stores/context'; + import { getDemoAppContext } from '$lib/stores/context'; import type { Base64Encoding, StringEncoding } from '$lib/types'; - import { copyToClipboard } from '$lib/util'; import type { EncodingEvent } from '$lib/xstate/b64Encode'; import { createTestSet } from '$lib/xstate/b64Encode.test/testSetGenerator'; - const { state, demoState, demoUIState, eventLog, send } = getAppContext(); - + const { state, demoState, demoUIState, send } = getDemoAppContext(); let inputText = defaultEncoderInput.inputText; let inputTextEncoding: StringEncoding = defaultEncoderInput.inputEncoding; let outputBase64Encoding: Base64Encoding = defaultEncoderInput.outputEncoding; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/CopyEncodedText.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/CopyEncodedText.svelte index 89673b67..26e1ded2 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/CopyEncodedText.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/CopyEncodedText.svelte @@ -1,8 +1,8 @@ diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte index 3ed37cfc..604848d1 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte @@ -1,12 +1,12 @@ diff --git a/apps/svelte-base64/src/lib/components/Results/LookupTables/LookupTables.svelte b/apps/svelte-base64/src/lib/components/Results/LookupTables/LookupTables.svelte index b1778c13..5ea946f1 100644 --- a/apps/svelte-base64/src/lib/components/Results/LookupTables/LookupTables.svelte +++ b/apps/svelte-base64/src/lib/components/Results/LookupTables/LookupTables.svelte @@ -1,8 +1,13 @@ diff --git a/apps/svelte-base64/src/lib/components/Visualization/EncodedChunk.svelte b/apps/svelte-base64/src/lib/components/Visualization/EncodedChunk.svelte index 6d8e47a9..2a821a23 100644 --- a/apps/svelte-base64/src/lib/components/Visualization/EncodedChunk.svelte +++ b/apps/svelte-base64/src/lib/components/Visualization/EncodedChunk.svelte @@ -1,7 +1,11 @@ diff --git a/apps/svelte-base64/src/routes/simple/+page.svelte b/apps/svelte-base64/src/routes/simple/+page.svelte index 8aa43535..e64086c0 100644 --- a/apps/svelte-base64/src/routes/simple/+page.svelte +++ b/apps/svelte-base64/src/routes/simple/+page.svelte @@ -1,7 +1,12 @@ From f487ec50bee27722e7dc23e301372c65df54e72a Mon Sep 17 00:00:00 2001 From: Aaron Luna Date: Sun, 28 Jan 2024 07:15:16 -0800 Subject: [PATCH 2/5] fix(svelte-base64): :bug: fix typescript errors --- apps/svelte-base64/src/lib/base64.ts | 69 +++++---- .../AlgorithmDemo/AlgorithmDemo.svelte | 62 ++++---- .../Buttons/OpenHelpDocsButton.svelte | 2 +- .../DemoResults/DemoResults.svelte | 17 ++- .../DemoResults/InputByte.svelte | 14 +- .../DemoResults/InputChunk.svelte | 16 +- .../DemoResults/OutputByte.svelte | 10 +- .../DemoResults/OutputBytePlaceholder.svelte | 6 +- .../DemoResults/OutputChunk.svelte | 10 +- .../AlgorithmDemo/DemoText/DemoText.svelte | 40 ++--- .../DemoText/Utf8/EncodedBytesForChar.svelte | 22 +-- .../AlgorithmDemo/DemoText/_demoText.ts | 42 +++--- .../AlgorithmDemo/FinalResults.svelte | 6 +- .../HelpDocs/HelpDocsModal.svelte | 4 +- .../AlgorithmDemo/HelpDocs/_helpSections.ts | 2 +- .../AlgorithmDemo/InputForm/InputForm.svelte | 2 +- .../NavButtons/GoToLastStepButton.svelte | 2 +- .../NavButtons/GoToNextStepButton.svelte | 2 +- .../InputForm/NavButtons/NavButton.svelte | 10 +- .../InputForm/NavButtons/NavButtons.svelte | 2 +- .../NavButtons/StartAutoPlayButton.svelte | 2 +- .../AlgorithmDemo/LookupTables.svelte | 8 +- .../src/lib/components/RadioButtons.svelte | 17 ++- .../src/lib/components/Select/Select.svelte | 11 +- .../Visualization/EncodedChunk.svelte | 21 ++- apps/svelte-base64/src/lib/constants.ts | 54 ++++--- apps/svelte-base64/src/lib/dataPrep.ts | 39 +++-- apps/svelte-base64/src/lib/maps.ts | 2 +- apps/svelte-base64/src/lib/unicode/api.ts | 14 +- apps/svelte-base64/src/lib/unicode/mocks.ts | 140 ----------------- apps/svelte-base64/src/lib/unicode/utf8.ts | 44 +++--- apps/svelte-base64/src/lib/util.ts | 142 +++++++++++------- apps/svelte-base64/src/lib/validation.ts | 34 +++-- .../svelte-base64/src/lib/xstate/b64Encode.ts | 56 ++++--- apps/svelte-base64/src/routes/+error.svelte | 6 +- apps/svelte-base64/src/service-worker.ts | 9 +- 36 files changed, 458 insertions(+), 481 deletions(-) diff --git a/apps/svelte-base64/src/lib/base64.ts b/apps/svelte-base64/src/lib/base64.ts index 8b4bf099..de229913 100644 --- a/apps/svelte-base64/src/lib/base64.ts +++ b/apps/svelte-base64/src/lib/base64.ts @@ -1,4 +1,4 @@ -import { BIN_TO_HEX } from '$lib/constants'; +import { BIN_TO_HEX, defaultBase64ByteMap, defaultDecoderInputChunk, defaultHexByteMap } from '$lib/constants'; import { validateDecoderInput, validateEncoderInput } from '$lib/dataPrep'; import { getBase64Alphabet } from '$lib/maps'; import { isTextEncoding } from '$lib/typeguards'; @@ -75,12 +75,14 @@ function encodeChunk( const word2 = base64Digit6bit.substring(2, 6); const base64DigitHex = `${BIN_TO_HEX[word1]}${BIN_TO_HEX[word2]}`; const base64DigitDecimal = parseInt(base64DigitHex, 16); - const base64Digit = base64Alphabet[base64DigitDecimal]; + const base64Digit = base64Alphabet?.[base64DigitDecimal] ?? ''; return { bin: base64Digit6bit, dec: base64DigitDecimal, b64: base64Digit, isPad: false, + groupId: '', + bitGroups: [], }; }); if (isPadded) { @@ -88,9 +90,11 @@ function encodeChunk( Array.from({ length: padlength }, (_, i) => i).forEach(() => outputMap.push({ bin: '', - dec: null, + dec: 0, b64: '=', isPad: true, + groupId: '', + bitGroups: [], }), ); } @@ -142,19 +146,24 @@ function createHexMap(inputChunks: DecoderInputChunk[]): HexByteMap[] { const byteString = binary.slice(i * 8, i * 8 + 8); const bin_word1 = byteString.slice(0, 4); const bin_word2 = byteString.slice(4, 8); - const hex_word1 = BIN_TO_HEX[bin_word1]; - const hex_word2 = BIN_TO_HEX[bin_word2]; + const hex_word1 = BIN_TO_HEX[bin_word1] ?? ''; + const hex_word2 = BIN_TO_HEX[bin_word2] ?? ''; const byte = parseInt(`${bin_word1}${bin_word2}`, 2); const ascii = asciiStringFromByteArray([byte]); - const isWhiteSpace = /^\s+$/.test(ascii); + const char = String.fromCharCode(byte); + const isWhiteSpace = /^\s+$/.test(char); return { byte, bin_word1, bin_word2, hex_word1, hex_word2, - isWhiteSpace, ascii: isWhiteSpace ? 'ws' : ascii, + char, + isWhiteSpace, + groupId: '', + bitGroups: [], + characterId: '', }; }); } @@ -167,19 +176,21 @@ function mapHexBytesToBase64Chunks(hexMap: HexByteMap[], inputChunks: DecoderInp if (byteIndex === hexMap.length) { break; } - bytesInChunk.push(hexMap[byteIndex]); + const byteMap = hexMap[byteIndex] ?? defaultHexByteMap; + bytesInChunk.push(byteMap); } + const chunk = inputChunks[i] ?? defaultDecoderInputChunk; const bytes = bytesInChunk.map((hexMap) => hexMap.byte); const outputChunk = { - base64: inputChunks[i].base64, - binary: inputChunks[i].binary, + base64: chunk.base64, + binary: chunk.binary, ascii: asciiStringFromByteArray(bytes), hex: hexStringFromByteArray(bytes), hexBytes: hexStringFromByteArray(bytes, true, ' ').split(' '), bytes, isASCII: validateAsciiBytes(bytes), hexMap: bytesInChunk, - base64Map: inputChunks[i].inputMap, + base64Map: chunk.inputMap, }; return addBitGroupsToOutputChunk(outputChunk, i); }); @@ -199,37 +210,39 @@ function addBitGroupsToOutputChunk(chunk: OutputChunk, i: number): OutputChunk { const hexBits3a = base64Bits3b; const hexBits3b = base64Bits4; - const base64Digit1 = chunk.base64Map[0]; + const base64Digit1 = chunk.base64Map[0] ?? defaultBase64ByteMap; base64Digit1.groupId = `base64-chunk-${i + 1}-digit-1`; base64Digit1.bitGroups = [{ groupId: `hex-chunk-${i + 1}-byte-1`, bits: hexBits1a }]; - const base64Digit2 = chunk.base64Map[1]; + const base64Digit2 = chunk.base64Map[1] ?? defaultBase64ByteMap; base64Digit2.groupId = `base64-chunk-${i + 1}-digit-2`; base64Digit2.bitGroups = [ { groupId: `hex-chunk-${i + 1}-byte-1`, bits: hexBits1b }, { groupId: `hex-chunk-${i + 1}-byte-2`, bits: hexBits2a }, ]; - const base64Digit3 = chunk.base64Map[2]; + const base64Digit3 = chunk.base64Map[2] ?? defaultBase64ByteMap; base64Digit3.groupId = `base64-chunk-${i + 1}-digit-3`; base64Digit3.bitGroups = [ { groupId: `hex-chunk-${i + 1}-byte-2`, bits: hexBits2b }, { groupId: `hex-chunk-${i + 1}-byte-3`, bits: hexBits3a }, ]; - const base64Digit4 = chunk.base64Map[3]; + const base64Digit4 = chunk.base64Map[3] ?? defaultBase64ByteMap; base64Digit4.groupId = `base64-chunk-${i + 1}-digit-4`; base64Digit4.bitGroups = [{ groupId: `hex-chunk-${i + 1}-byte-3`, bits: hexBits3b }]; - chunk.hexMap[0].groupId = `hex-chunk-${i + 1}-byte-1`; - chunk.hexMap[0].bitGroups = [ + const hexByte1 = chunk.hexMap[0] ?? defaultHexByteMap; + hexByte1.groupId = `hex-chunk-${i + 1}-byte-1`; + hexByte1.bitGroups = [ { groupId: `base64-chunk-${i + 1}-digit-1`, bits: base64Bits1 }, { groupId: `base64-chunk-${i + 1}-digit-2`, bits: base64Bits2a }, ]; if (chunk.hexMap.length > 1) { - chunk.hexMap[1].groupId = `hex-chunk-${i + 1}-byte-2`; - chunk.hexMap[1].bitGroups = [ + const hexByte2 = chunk.hexMap[1] ?? defaultHexByteMap; + hexByte2.groupId = `hex-chunk-${i + 1}-byte-2`; + hexByte2.bitGroups = [ { groupId: `base64-chunk-${i + 1}-digit-2`, bits: base64Bits2b }, { groupId: `base64-chunk-${i + 1}-digit-3`, bits: base64Bits3a }, ]; @@ -241,8 +254,9 @@ function addBitGroupsToOutputChunk(chunk: OutputChunk, i: number): OutputChunk { } if (chunk.hexMap.length > 2) { - chunk.hexMap[2].groupId = `hex-chunk-${i + 1}-byte-3`; - chunk.hexMap[2].bitGroups = [ + const hexByte3 = chunk.hexMap[2] ?? defaultHexByteMap; + hexByte3.groupId = `hex-chunk-${i + 1}-byte-3`; + hexByte3.bitGroups = [ { groupId: `base64-chunk-${i + 1}-digit-3`, bits: base64Bits3b }, { groupId: `base64-chunk-${i + 1}-digit-4`, bits: base64Bits4 }, ]; @@ -265,7 +279,7 @@ function createEncodedCharacterMap(utf8: Utf8StringComposition, encodedChunks: O const updatedComplexCharMap: Utf8ComplexCharacterMap = { ...complexCharMap, hexMap: combinedHexMap }; combinedStart = combinedEnd; if (complexCharMap.isCombined) { - const standardCharMapWithHexMap = updatedComplexCharMap.charMap.map((standardCharMap) => { + const standardCharMapWithHexMap = updatedComplexCharMap.charMap?.map((standardCharMap) => { isolatedEnd += standardCharMap.totalBytes; const isolatedHexMap = hexMap.slice(isolatedStart, isolatedEnd); const updatedStandardCharMap: Utf8StandardCharacterMap = { ...standardCharMap, hexMap: isolatedHexMap }; @@ -277,9 +291,12 @@ function createEncodedCharacterMap(utf8: Utf8StringComposition, encodedChunks: O return updatedComplexCharMap; }); const updatedHexMaps = complexCharMapWithHexMap.map((complexCharMap) => { - const hexMapForChar = complexCharMap.hexMap; - hexMapForChar[0].char = complexCharMap.char; - hexMapForChar.slice(1).forEach((hexMap) => (hexMap.char = ' ')); + const hexMapForChar = complexCharMap.hexMap ?? []; + const [firstCharHexMap, ...remainingHexMaps] = hexMapForChar; + if (firstCharHexMap) { + firstCharHexMap.char = complexCharMap.char; + } + remainingHexMaps.forEach((hexMap) => (hexMap.char = ' ')); return hexMapForChar; }); return { ...utf8, charMap: complexCharMapWithHexMap, hexMap: updatedHexMaps.flat() }; @@ -287,5 +304,5 @@ function createEncodedCharacterMap(utf8: Utf8StringComposition, encodedChunks: O function updateEncoderOutputChunks(utf8: Utf8StringComposition, encodedChunks: OutputChunk[]): OutputChunk[] { const hexMapsChunked = chunkify({ inputList: utf8.hexMap, chunkSize: 3 }); - return encodedChunks.map((chunk, i) => ({ ...chunk, hexMap: hexMapsChunked[i] })); + return encodedChunks.map((chunk, i) => ({ ...chunk, hexMap: hexMapsChunked[i] ?? [] })); } diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte index aa8823af..c0dc5597 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/AlgorithmDemo.svelte @@ -13,7 +13,6 @@ import { getDemoAppContext } from '$lib/stores/context'; import type { Base64Encoding, StringEncoding } from '$lib/types'; import type { EncodingEvent } from '$lib/xstate/b64Encode'; - import { createTestSet } from '$lib/xstate/b64Encode.test/testSetGenerator'; const { state, demoState, demoUIState, send } = getDemoAppContext(); let inputText = defaultEncoderInput.inputText; @@ -21,26 +20,29 @@ let outputBase64Encoding: Base64Encoding = defaultEncoderInput.outputEncoding; let helpModal: HelpDocsModal; - $: if ($state.context.autoplay && $state.value) eventLog.add({ type: 'AUTOPLAYING' }); + // $: if ($state.context.autoplay && $state.value) eventLog.add({ type: 'AUTOPLAYING' }); $: if (inputText) updateInputText(inputText, inputTextEncoding, outputBase64Encoding); - $: if ($demoState.errorOccurred) $alert = $state.context.input.validationResult.error?.message ?? ''; - $: if ($demoState.startedSubProcess) { + $: if ($demoState?.errorOccurred) $alert = $state.context.input.validationResult.error?.message ?? ''; + $: if ($demoState?.startedSubProcess) { $demoUIState.highlightHexByte = undefined; $demoUIState.highlightBase64 = ''; } - $: if ($state.matches({ encodeInput: 'autoPlayEncodeByte' }) || $state.matches({ encodeInput: 'encodeByte' })) { + $: if ($state?.matches({ encodeInput: 'autoPlayEncodeByte' }) || $state?.matches({ encodeInput: 'encodeByte' })) { $demoUIState.highlightHexByte = $state.context.currentByte.byte; } - $: if ($state.matches({ encodeOutput: 'autoPlayEncodeBase64' }) || $state.matches({ encodeOutput: 'encodeBase64' })) { + $: if ( + $state?.matches({ encodeOutput: 'autoPlayEncodeBase64' }) || + $state?.matches({ encodeOutput: 'encodeBase64' }) + ) { $demoUIState.highlightBase64 = $state.context.currentBase64Char.b64; } - $: if ($state.context.resetForm) { + $: if ($state?.context.resetForm) { inputText = defaultEncoderInput.inputText; inputTextEncoding = defaultEncoderInput.inputEncoding; outputBase64Encoding = defaultEncoderInput.outputEncoding; } - $: bottomRowHeight = $demoState.isMobileDisplay ? 'auto' : '260px'; - $: formTitleFontSize = $demoState.isMobileDisplay ? '1.6rem' : '1.9rem'; + $: bottomRowHeight = $demoState?.isMobileDisplay ? 'auto' : '260px'; + $: formTitleFontSize = $demoState?.isMobileDisplay ? '1.6rem' : '1.9rem'; // $: if ($demoState.dev) { // const test = '∑ßåœ ≈ ∆c'; @@ -112,27 +114,27 @@ if (key === 'KeyC') { console.log({ context: $state.context }); } - if (key === 'KeyE') { - console.log({ log: eventLog.entries() }); - } - if (key === 'KeyL') { - eventLog.clear(); - console.log({ $eventLog }); - } if (key === 'KeyS') { console.log({ state: $state.value }); } - if (key === 'KeyT') { - const result = await copyToClipboard(createTestSet()); - if (result.success) { - console.log('Successfully created test set and copied to clipboard!'); - } - } + // if (key === 'KeyE') { + // console.log({ log: eventLog.entries() }); + // } + // if (key === 'KeyL') { + // eventLog.clear(); + // console.log({ $eventLog }); + // } + // if (key === 'KeyT') { + // const result = await copyToClipboard(createTestSet()); + // if (result.success) { + // console.log('Successfully created test set and copied to clipboard!'); + // } + // } } function sendEvent(action: EncodingEvent) { if ($state.can(action)) { - eventLog.add(action); + // eventLog.add(action); send(action); } } @@ -161,10 +163,10 @@
- {#if $state.matches('inactive') || $state.matches({ validateInputText: 'error' })} + {#if $state?.matches('inactive') || $state?.matches({ validateInputText: 'error' })} openHelpDocsModal(e.detail)} /> {:else} openHelpDocsModal(e.detail)} /> @@ -176,8 +178,8 @@
@@ -268,10 +270,10 @@ grid-area: demo-steps; } .demo-steps { - grid-template-columns: 148px 5px 353px 5px 122px; + grid-template-columns: 161px 0px 361px 0px 115px; grid-template-rows: auto auto auto auto; align-items: flex-start; - column-gap: 0.5rem; + column-gap: 0.25rem; } #demo-text { grid-column: 1 / span 5; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/OpenHelpDocsButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/OpenHelpDocsButton.svelte index 75fc372f..45d15d72 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/OpenHelpDocsButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/Buttons/OpenHelpDocsButton.svelte @@ -6,7 +6,7 @@ export let label: string; export let helpTopic: string = 'why-base64-1'; export let helpTopicsExpanded = false; - export let name: string = null; + export let name: string = ''; export let disabled = false; export let margin = '0'; export let style = ''; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/DemoResults.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/DemoResults.svelte index caffdd30..a1d3cef8 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/DemoResults.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/DemoResults.svelte @@ -4,6 +4,7 @@ import OutputByte from '$lib/components/AlgorithmDemo/DemoResults/OutputByte.svelte'; import OutputBytePlaceholder from '$lib/components/AlgorithmDemo/DemoResults/OutputBytePlaceholder.svelte'; import OutputChunk from '$lib/components/AlgorithmDemo/DemoResults/OutputChunk.svelte'; + import { defaultEncoderInputChunk } from '$lib/constants'; import { getDemoAppContext } from '$lib/stores/context'; import type { Base64ByteMap, HexByteMap } from '$lib/types'; import { getChunkIndexFromBase64CharIndex, getChunkIndexFromByteIndex } from '$lib/util'; @@ -22,19 +23,20 @@ } -{#if $demoState.showInputBytes} +{#if $demoState?.showInputBytes}

Input

{#each $state.context.updatedByteMaps as byte, byteIndex}
highlightHexByteValue(true, byte)} on:mouseleave={() => highlightHexByteValue(false, byte)} > @@ -44,22 +46,22 @@
{/if} -{#if $demoState.showInputChunks} +{#if $demoState?.showInputChunks}
{#each $state.context.updatedInputChunks as chunk, i} {/each}
{/if} -{#if $demoState.showOutputChunks} +{#if $demoState?.showOutputChunks}
{#each $state.context.updatedOutputChunks as chunk, i} - + {/each}
{/if} -{#if $demoState.showOutputBytePlaceholders} +{#if $demoState?.showOutputBytePlaceholders}

Output

@@ -76,12 +78,13 @@
{/if} -{#if $demoState.showOutputBytes} +{#if $demoState?.showOutputBytes}

Output

{#each $state.context.updatedBase64Maps as b64, charIndex}
$state.matches('verifyResults') && currentGroupId === checkGroupId; const getBase64CharColor = (groupId: string): string => - rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length] ?? '--purple3'; const highlightBitGroup = (base64CharIndex: number, groupId: string): boolean => b64MappingInProgress && base64CharIndex === getBase64CharIndexFromGroupId(groupId); const getCurrentBitGroupColor = (base64CharIndex: number, currentGroupId: string, checkGroupId: string): string => diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/InputChunk.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/InputChunk.svelte index 88526c2f..35683fd2 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/InputChunk.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/InputChunk.svelte @@ -10,14 +10,14 @@ const { state, demoUIState } = getDemoAppContext(); $: chunkNumber = chunkIndex + 1; - $: chunkColor = rotatingColors[chunkIndex % rotatingColors.length]; + $: chunkColor = rotatingColors[chunkIndex % rotatingColors.length] ?? '--teal4'; $: chunkIdColor = $state.matches('verifyResults') ? '--light-gray3' : chunkColor; $: chunkMappingInProgress = $state.matches({ createInputChunks: 'autoPlayCreateInputChunk' }) || $state.matches({ createInputChunks: 'createInputChunk' }) || $state.matches({ createInputChunks: 'createLastPaddedChunk' }); $: highlightChunk = chunkMappingInProgress && $state.context.inputChunkIndex === chunkIndex; - $: finalBase64GroupId = chunk.inputMap.slice(-1)[0].bitGroups.slice(-1)[0].groupId; + $: finalBase64GroupId = chunk.inputMap.slice(-1)[0]?.bitGroups.slice(-1)[0]?.groupId ?? ''; $: highlightPadBits = chunk.isPadded && $state.matches({ createInputChunks: 'explainLastPaddedChunk' }); $: byteMappingInProgress = $state.matches({ encodeInput: 'autoPlayEncodeByte' }) || @@ -28,10 +28,10 @@ $state.matches('verifyResults') && currentGroupId === checkGroupId; const getHexByteColor = (groupId: string): string => - rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length] ?? '--green3'; const getBase64CharColor = (groupId: string): string => - rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length] ?? '--purple3'; const highlightBitGroup = (base64CharIndex: number, groupId: string): boolean => byteMappingInProgress && base64CharIndex === getBase64CharIndexFromGroupId(groupId); const getCurrentB64BitGroupColor = ( @@ -45,10 +45,10 @@ highlightBitGroup(base64CharIndex, checkB64GroupId) || bitGroupIsHovered(currentB64GroupId, checkB64GroupId) ? getBase64CharColor(checkB64GroupId) : bitGroupIsHovered(currentHexGroupId, checkHexGroupId) - ? getHexByteColor(checkHexGroupId) - : highlightChunk && !padding - ? chunkColor - : '--light-gray3'; + ? getHexByteColor(checkHexGroupId) + : highlightChunk && !padding + ? chunkColor + : '--light-gray3';
$state.matches('verifyResults') && currentGroupId === checkGroupId; const getHexByteColor = (groupId: string): string => - rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length] ?? '--green3'; const getCurrentBitGroupColor = (currentGroupId: string, checkGroupId: string): string => bitGroupIsHovered(currentGroupId, checkGroupId) ? getHexByteColor(checkGroupId) : currentB64CharColor; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputBytePlaceholder.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputBytePlaceholder.svelte index dc4aaba8..41fa95ec 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputBytePlaceholder.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputBytePlaceholder.svelte @@ -1,12 +1,12 @@ diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputChunk.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputChunk.svelte index 42062581..612b9136 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputChunk.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoResults/OutputChunk.svelte @@ -10,7 +10,7 @@ const { state, demoUIState } = getDemoAppContext(); $: chunkNumber = chunkIndex + 1; - $: chunkColor = rotatingColors[chunkIndex % rotatingColors.length]; + $: chunkColor = rotatingColors[chunkIndex % rotatingColors.length] ?? '--teal4'; $: chunkIdColor = $state.matches('verifyResults') ? '--light-gray3' : chunkColor; $: currentInputChunk = $state.context.inputChunkIndex; $: currentOutputChunk = $state.context.outputChunkIndex; @@ -33,10 +33,10 @@ $state.matches('verifyResults') && currentGroupId === checkGroupId; const getHexByteColor = (groupId: string): string => - rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getHexByteIndexFromGroupId(groupId) % rotatingColors.length] ?? '--green3'; const getBase64CharColor = (groupId: string): string => - rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length]; + rotatingColors[getBase64CharIndexFromGroupId(groupId) % rotatingColors.length] ?? '--purple3'; const highlightBitGroup = (base64CharIndex: number, groupId: string): boolean => !stateName.includes('idle') && stateName.includes('encodeOutput') && @@ -51,8 +51,8 @@ highlightBitGroup(base64CharIndex, checkB64GroupId) || bitGroupIsHovered(currentB64GroupId, checkB64GroupId) ? getBase64CharColor(checkB64GroupId) : bitGroupIsHovered(currentHexGroupId, checkHexGroupId) - ? getHexByteColor(checkHexGroupId) - : currentChunkColor; + ? getHexByteColor(checkHexGroupId) + : currentChunkColor; const getCurrentBitGroupOutlineStyle = ( base64CharIndex: number, currentB64GroupId: string, diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/DemoText.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/DemoText.svelte index 6a47fa05..662bcb94 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/DemoText.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/DemoText.svelte @@ -26,24 +26,24 @@ const lcmSolveUrl = 'https://www.calculatorsoup.com/calculators/math/lcm.php?input=8+6&data=multiples_method&action=solve'; - $: encodingIn = formatEncodingType($state.context.input.inputEncoding); - $: finalBase64CharNumber = $state.context.input.lastChunkPadded + $: encodingIn = formatEncodingType($state?.context.input.inputEncoding); + $: finalBase64CharNumber = $state?.context.input.lastChunkPadded ? $state.context.byteMaps.length % 3 === 1 ? $state.context.base64Maps.length - 2 : $state.context.base64Maps.length - 1 - : $state.context.base64Maps.length; - $: finalInputChunk = $state.context.input.chunks?.slice(-1)[0] || defaultEncoderInputChunk; + : $state?.context.base64Maps.length; + $: finalInputChunk = $state?.context.input.chunks?.slice(-1)[0] || defaultEncoderInputChunk; $: finalInputChunkSize = finalInputChunk?.bytes.length; $: finalInputChunkSizeVerbose = finalInputChunkSize === 2 ? '18 bits (two 8-bit bytes + 2 pad bits)' : '12 bits (one 8-bit byte + 4 pad bits)'; - $: finalChunkBase64 = $state.context.output.chunks?.slice(-1)[0]?.base64 || ''; + $: finalChunkBase64 = $state?.context.output.chunks?.slice(-1)[0]?.base64 || ''; -{#if $state.matches({ validateInputText: 'success' })} +{#if $state?.matches({ validateInputText: 'success' })}

Nicely done! The value you provided looks, smells and tastes like a valid {encodingIn} string.

-{:else if $state.matches({ encodeInput: 'idle' })} +{:else if $state?.matches({ encodeInput: 'idle' })} {#each getEncodeInputText_IdleDemoText($state.context.input.inputText, $state.context.input.inputEncoding) as text}

{@html text}

{/each} @@ -53,7 +53,7 @@ {/if} {/if} -{:else if $state.matches({ encodeInput: 'autoPlayEncodeByte' }) || $state.matches({ encodeInput: 'encodeByte' })} +{:else if $state?.matches({ encodeInput: 'autoPlayEncodeByte' }) || $state?.matches({ encodeInput: 'encodeByte' })}

{@html describeInputByte( $state.context.currentByte.byte, @@ -62,7 +62,7 @@ $state.context.input.inputEncoding, )}

-{:else if $state.matches({ encodeInput: 'explainByteMapping' })} +{:else if $state?.matches({ encodeInput: 'explainByteMapping' })}

The first step is complete: the input data has been converted to a sequence of 8-bit bytes.

However, in Base64 encoding each value is stored as a 6-bit byte (see the table below which shows the @@ -73,7 +73,7 @@ In order to reconcile the differing byte sizes, we need to find a number that is evenly divisible by both 8 and 6.

-{:else if $state.matches({ createInputChunks: 'regularIdle' }) || $state.matches({ createInputChunks: 'autoPlayIdle' })} +{:else if $state?.matches( { createInputChunks: 'regularIdle' }, ) || $state?.matches( { createInputChunks: 'autoPlayIdle' }, )}

In mathematics, this value is called the Least Common Multple Therefore, if we separate the input data into chunks of three bytes, each chunk can be encoded as four Base64 digts.

-{:else if $state.matches( { createInputChunks: 'autoPlayCreateInputChunk' }, ) || $state.matches( { createInputChunks: 'createInputChunk' }, ) || $state.matches( { createInputChunks: 'createLastPaddedChunk' }, )} +{:else if $state?.matches( { createInputChunks: 'autoPlayCreateInputChunk' }, ) || $state?.matches( { createInputChunks: 'createInputChunk' }, ) || $state?.matches( { createInputChunks: 'createLastPaddedChunk' }, )}

{@html describeInputChunk( $state.context.currentInputChunk, @@ -100,12 +100,12 @@ $state.context.input?.totalChunks || 0, )}

-{:else if $state.matches({ createInputChunks: 'explainLastPaddedChunk' })} +{:else if $state?.matches({ createInputChunks: 'explainLastPaddedChunk' })} {#each explainLastPaddedInputChunk($state.context.currentInputChunk, $state.context.input?.totalChunks || 0) as text}

{@html text}

{/each} -{:else if $state.matches( { createOutputChunks: 'regularIdle' }, ) || $state.matches( { createOutputChunks: 'autoPlayIdle' }, )} +{:else if $state?.matches( { createOutputChunks: 'regularIdle' }, ) || $state?.matches( { createOutputChunks: 'autoPlayIdle' }, )}

Next, for each chunk of input data with 24 bits (three 8-bit bytes), an output chunk with four 6-bit bytes is created from the same sequence of bits. @@ -116,13 +116,13 @@ The last chunk will require special processing since it only contains {finalInputChunkSizeVerbose}.

{/if} -{:else if $state.matches( { createOutputChunks: 'autoPlayCreateOutputChunk' }, ) || $state.matches( { createOutputChunks: 'createOutputChunk' }, ) || $state.matches( { createOutputChunks: 'createLastPaddedChunk' }, )} +{:else if $state?.matches( { createOutputChunks: 'autoPlayCreateOutputChunk' }, ) || $state?.matches( { createOutputChunks: 'createOutputChunk' }, ) || $state?.matches( { createOutputChunks: 'createLastPaddedChunk' }, )} {#each describeOutputChunk($state.context.currentOutputChunk, $state.context.outputChunkIndex, $state.context.input?.totalChunks || 0) as text}

{@html text}

{/each} -{:else if $state.matches({ createOutputChunks: 'explainLastPaddedChunk' })} +{:else if $state?.matches({ createOutputChunks: 'explainLastPaddedChunk' })}

{@html explainLastPaddedOutputChunk(finalInputChunk)[0]}

@@ -134,11 +134,11 @@

{@html explainLastPaddedOutputChunk(finalInputChunk)[1]}

-{:else if $state.matches({ createOutputChunks: 'explainPadCharacter' })} +{:else if $state?.matches({ createOutputChunks: 'explainPadCharacter' })} {#each explainPadCharacter($state.context.currentOutputChunk) as text}

{@html text}

{/each} -{:else if $state.matches({ encodeOutput: 'idle' })} +{:else if $state?.matches({ encodeOutput: 'idle' })}

The final step is to convert each 6-bit value to the corresponding Base64 digit. The table below shows all 64 digits in the {getBase64AlphabetVerbose($state.context.input.outputEncoding)} and their decimal and binary values. @@ -146,20 +146,20 @@

As each 6-bit value is converted to a Base64 digit, the corresponding row in the table below will be highlighted.

-{:else if $state.matches({ encodeOutput: 'autoPlayEncodeBase64' }) || $state.matches({ encodeOutput: 'encodeBase64' })} +{:else if $state?.matches( { encodeOutput: 'autoPlayEncodeBase64' }, ) || $state?.matches( { encodeOutput: 'encodeBase64' }, )} {#each describeBase64Char($state.context.currentBase64Char, $state.context.base64CharIndex, finalBase64CharNumber, $state.context.output.outputEncoding, finalChunkBase64) as text}

{@html text}

{/each} -{:else if $state.matches('verifyResults')} +{:else if $state?.matches('verifyResults')}

The input data has been successfully encoded as a string of Base64 characters!

By hovering the mouse over any of the input/output bytes, you can inspect the relationships between the various groups of bits.

When you are ready, proceed to the next step to see the final results.

-{:else if $state.matches('finished')} +{:else if $state?.matches('finished')}

The encoding process is complete!

{/if} diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/Utf8/EncodedBytesForChar.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/Utf8/EncodedBytesForChar.svelte index aab22d91..cbc8e0d8 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/Utf8/EncodedBytesForChar.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/Utf8/EncodedBytesForChar.svelte @@ -18,7 +18,7 @@ export let isCombined: boolean; export let charMap: Utf8StandardCharacterMap[] | undefined; export let expanded = false; - const dispatch = createEventDispatcher<{ toggled: never }>(); + const dispatch = createEventDispatcher<{ toggled: null }>(); const { demoState } = getDemoAppContext(); const isVS15 = (encoded: string): boolean => encoded === '%EF%B8%8E'; @@ -30,12 +30,12 @@ isVS15(encoded) || isVS16(encoded) ? 'variation' : isZWJ(encoded) - ? 'zwj' - : isWhiteSpace(encoded) - ? 'whitespace' - : isASCII - ? 'ascii' - : 'char'; + ? 'zwj' + : isWhiteSpace(encoded) + ? 'whitespace' + : isASCII + ? 'ascii' + : 'char'; const getCharToDisplay = (char: string, encoded: string): string => isVS15(encoded) ? 'VS15' : isVS16(encoded) ? 'VS16' : isZWJ(encoded) ? 'ZWJ' : isWhiteSpace(encoded) ? 'SP' : char; @@ -46,13 +46,13 @@ $: buttonPlaceholderFlexMobile = anyCharsAreExpanded ? 'flex: 0 0 30px;' : anyCharsAreCombined - ? 'flex: 0 0 20px;' - : 'flex: 0;'; + ? 'flex: 0 0 20px;' + : 'flex: 0;'; $: buttonPlaceholderFlexLarge = anyCharsAreExpanded ? 'flex: 0 0 25px;' : anyCharsAreCombined - ? 'flex: 0 0 20px;' - : 'flex: 0;'; + ? 'flex: 0 0 20px;' + : 'flex: 0;'; $: buttonPlaceholderFlex = $demoState.isMobileDisplay ? buttonPlaceholderFlexMobile : buttonPlaceholderFlexLarge; export function expand() { diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/_demoText.ts b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/_demoText.ts index 96e3f423..5753d2b5 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/_demoText.ts +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoText/_demoText.ts @@ -15,12 +15,12 @@ const convertNumber = (num: number) => (num < 4 || num > 20) && num.toString().slice(-1)[0] === '1' ? `${num}st` : (num < 4 || num > 20) && num.toString().slice(-1)[0] === '2' - ? `${num}nd` - : (num < 4 || num > 20) && num.toString().slice(-1)[0] === '3' - ? `${num}rd` - : `${num}th`; + ? `${num}nd` + : (num < 4 || num > 20) && num.toString().slice(-1)[0] === '3' + ? `${num}rd` + : `${num}th`; -const getSequentialColor = (i: number): string => rotatingColors[i % rotatingColors.length]; +const getSequentialColor = (i: number): string => rotatingColors[i % rotatingColors.length] ?? '--green3'; const getByteNumHtml = (num: number, colorNum: number) => `
diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/HelpDocsModal.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/HelpDocsModal.svelte index 0fd4178e..9d04742f 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/HelpDocsModal.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/HelpDocsModal.svelte @@ -13,8 +13,8 @@ let closed: boolean; const { demoState, demoUIState } = getDemoAppContext(); - $: $demoUIState.modalOpen = !closed; - $: showContentsPanel = $demoState.pageWidth >= 764; + $: if ($demoUIState) $demoUIState.modalOpen = !closed; + $: showContentsPanel = $demoState?.pageWidth >= 764; $: displayedSectionTitle = helpTopicsExpanded ? 'Help Topics' : encodingHelpSections[index]?.title; const getNextIndex = (i: number) => (i + 1) % encodingHelpSections.length; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/_helpSections.ts b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/_helpSections.ts index 3a674e1a..eaa7386c 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/_helpSections.ts +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/_helpSections.ts @@ -40,4 +40,4 @@ const createEncodingHelpSections = (): HelpSection[] => [ export const encodingHelpSections = createEncodingHelpSections(); export const getHelpTopicIndex = (id: string): number => - encodingHelpSections.find((section) => section.id === id).index ?? 0; + encodingHelpSections.find((section) => section.id === id)?.index ?? 0; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/InputForm.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/InputForm.svelte index 452d7d22..6e049289 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/InputForm.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/InputForm.svelte @@ -13,7 +13,7 @@ const { state } = getDemoAppContext(); $: inputTextBoxStyles = 'flex: 1;'; - $: controlsDisabled = !$state.matches('inactive') && !$state.matches({ validateInputText: 'error' }); + $: controlsDisabled = !$state?.matches('inactive') && !$state?.matches({ validateInputText: 'error' }); $: error = inputText && !$state.matches('inactive') && diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToLastStepButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToLastStepButton.svelte index 414cdd7d..ee5bd519 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToLastStepButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToLastStepButton.svelte @@ -10,7 +10,7 @@ let defaultNavAction: EncodingEvent = { type: 'GO_TO_LAST_STEP' }; let encodingStateToEventMap: EncodingStateToEventMap = [ { - requiredState: { value: 'inactive', context: $state.context }, + requiredState: { value: 'inactive', context: $state?.context }, navAction: () => ({ type: 'SKIP_DEMO', inputText: $state?.context.input.inputText, diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToNextStepButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToNextStepButton.svelte index 14d4b70e..9c850ff3 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToNextStepButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/GoToNextStepButton.svelte @@ -10,7 +10,7 @@ let defaultNavAction: EncodingEvent = { type: 'GO_TO_NEXT_STEP' }; let encodingStateToEventMap: EncodingStateToEventMap = [ { - requiredState: { value: 'inactive', context: $state.context }, + requiredState: { value: 'inactive', context: $state?.context }, navAction: () => ({ type: 'VALIDATE_TEXT', inputText: $state?.context.input.inputText, diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButton.svelte index dc0da9d2..909ffea5 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButton.svelte @@ -4,8 +4,8 @@ import type { EncodingEvent } from '$lib/xstate/b64Encode'; import { fade } from 'svelte/transition'; - export let defaultNavAction: EncodingEvent = null; - export let encodingStateToEventMap: EncodingStateToEventMap = null; + export let defaultNavAction: EncodingEvent; + export let encodingStateToEventMap: EncodingStateToEventMap | undefined = undefined; export let label: string = ''; export let tooltip: string = ''; export let buttonNumber: number = 0; @@ -16,6 +16,10 @@ let duration = 1250; let timeout: NodeJS.Timeout; const { state, demoState, send } = getDemoAppContext(); + + $: labelColor = $state?.context.autoplay + ? `var(--nav-button-autoplay-bg-color)` + : `var(--nav-button-active-bg-color)`; $: labelStyle = `grid-column: ${buttonNumber} / span 1; grid-row: 1 / span 1; color: ${labelColor}`; $: butttonStyle = `grid-column: ${buttonNumber} / span 1; grid-row: 2 / span 1;`; $: validActions = encodingStateToEventMap @@ -55,7 +59,7 @@ function fireNavAction() { const action = getNavAction(); if ($state.can(action)) { - eventLog.add(action); + // eventLog.add(action); send(action); } } diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButtons.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButtons.svelte index b6587c7b..09987390 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButtons.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/NavButtons.svelte @@ -10,7 +10,7 @@ const { state } = getDemoAppContext(); - $: autoplay = $state.context.autoplay && !$state.matches({ validateInputText: 'error' }); + $: autoplay = $state?.context.autoplay && !$state?.matches({ validateInputText: 'error' });
diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte index 604848d1..f6c5599f 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/InputForm/NavButtons/StartAutoPlayButton.svelte @@ -10,7 +10,7 @@ let defaultNavAction: EncodingEvent = { type: 'RESUME_AUTO_PLAY' }; let encodingStateToEventMap: EncodingStateToEventMap = [ { - requiredState: { value: 'inactive', context: $state.context }, + requiredState: { value: 'inactive', context: $state?.context }, navAction: () => ({ type: 'START_AUTOPLAY', inputText: $state?.context.input.inputText, diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/LookupTables.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/LookupTables.svelte index b6c15753..fd97c749 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/LookupTables.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/LookupTables.svelte @@ -10,16 +10,14 @@ export let highlightBase64: string; const { demoState } = getDemoAppContext(); - const { demoState } = getAppContext(); - - $: tableChunkSize = $demoState.isMobileDisplay ? 32 : 16; + $: tableChunkSize = $demoState?.isMobileDisplay ? 32 : 16; -{#if $demoState.showAsciiTable} +{#if $demoState?.showAsciiTable}
-{:else if $demoState.showBase64Table} +{:else if $demoState?.showBase64Table}
import { getSimpleAppContext } from '$lib/stores/context'; import type { AppStore } from '$lib/types'; + import type { RadioButtonDetails } from '@a-luna/shared-ui'; import { createEventDispatcher } from 'svelte'; import type { Readable } from 'svelte/store'; @@ -12,8 +13,8 @@ export let groupId = ''; export let groupName = ''; export let style: string; - export let buttons = []; - let instances = {}; + export let buttons: RadioButtonDetails[] = []; + let instances: { [k: string]: HTMLInputElement } = {}; const radioButtonSelectionChangedEventDispatcher = createEventDispatcher<{ radioButtonSelectionChanged: { groupId: string; groupName: string; selectionId: string; value: string }; }>(); @@ -24,7 +25,13 @@ : 'margin: 0 auto 0 0.5rem;' : 'margin: 0 auto 0 0.5rem;'; - export const reset = () => buttons.forEach((button) => (instances[button.id].checked = button.checked)); + export const reset = () => + buttons.forEach((button: RadioButtonDetails) => { + const thisInstance = instances[button.id]; + if (thisInstance) { + thisInstance.checked = button.checked; + } + }); function raiseSelectionChanged(id: string, value: string) { radioButtonSelectionChangedEventDispatcher('radioButtonSelectionChanged', { @@ -40,7 +47,7 @@
{title}
- {#each buttons as button, i} + {#each buttons as button}
raiseSelectionChanged(button.id, button.value)} + on:change={(_) => raiseSelectionChanged(button.id, button.value)} />
diff --git a/apps/svelte-base64/src/lib/components/Select/Select.svelte b/apps/svelte-base64/src/lib/components/Select/Select.svelte index 792bab90..961911e9 100644 --- a/apps/svelte-base64/src/lib/components/Select/Select.svelte +++ b/apps/svelte-base64/src/lib/components/Select/Select.svelte @@ -3,9 +3,10 @@ @@ -28,6 +28,7 @@
{#each chunk.hexMap as hexMap}
{#each chunk.base64Map as b64Map}
diff --git a/apps/svelte-base64/src/lib/constants.ts b/apps/svelte-base64/src/lib/constants.ts index dde9836c..3a692331 100644 --- a/apps/svelte-base64/src/lib/constants.ts +++ b/apps/svelte-base64/src/lib/constants.ts @@ -99,6 +99,7 @@ export const defaultHexByteMap: HexByteMap = { hex_word1: '', hex_word2: '', ascii: '', + char: '', isWhiteSpace: false, groupId: '', bitGroups: [ @@ -107,6 +108,7 @@ export const defaultHexByteMap: HexByteMap = { bits: '', }, ], + characterId: '', }; export const defaultEncoderInputChunk: EncoderInputChunk = { @@ -154,31 +156,6 @@ export const defaultDecoderOutput: DecoderOutput = { chunks: [defaultOutputChunk], }; -export const defaultEncoderInput: EncoderInput = { - inputText: '', - inputEncoding: 'utf8', - outputEncoding: 'base64', - validationResult: { success: true }, - bytes: [], - hex: '', - ascii: '', - binary: '', - totalChunks: 0, - lastChunkPadded: false, - padLength: 0, - chunks: [defaultEncoderInputChunk], -}; - -export const defaultEncoderOutput: EncoderOutput = { - input: '', - inputEncoding: 'ascii', - isASCII: true, - output: '', - bytes: [], - outputEncoding: 'base64', - chunks: [defaultOutputChunk], -}; - export const defaultUtf8StandardCharacterMap: Utf8StandardCharacterMap = { char: '', isCombined: false, @@ -220,3 +197,30 @@ export const defaultUtf8StringComposition: Utf8StringComposition = { bytes: [], charMap: [defaultUtf8ComplexCharacterMap], }; + +export const defaultEncoderInput: EncoderInput = { + inputText: '', + inputEncoding: 'utf8', + outputEncoding: 'base64', + validationResult: { success: true }, + bytes: [], + hexBytes: [], + hex: '', + ascii: '', + utf8: defaultUtf8StringComposition, + binary: '', + totalChunks: 0, + lastChunkPadded: false, + padLength: 0, + chunks: [defaultEncoderInputChunk], +}; + +export const defaultEncoderOutput: EncoderOutput = { + input: '', + inputEncoding: 'ascii', + isASCII: true, + output: '', + bytes: [], + outputEncoding: 'base64', + chunks: [defaultOutputChunk], +}; diff --git a/apps/svelte-base64/src/lib/dataPrep.ts b/apps/svelte-base64/src/lib/dataPrep.ts index 8eff3c61..de14258e 100644 --- a/apps/svelte-base64/src/lib/dataPrep.ts +++ b/apps/svelte-base64/src/lib/dataPrep.ts @@ -1,4 +1,4 @@ -import { BIN_TO_HEX, defaultDecoderInput, defaultEncoderInput } from '$lib/constants'; +import { BIN_TO_HEX, defaultDecoderInput, defaultEncoderInput, defaultUtf8StringComposition } from '$lib/constants'; import { getBase64LookupMap } from '$lib/maps'; import { isTextEncoding } from '$lib/typeguards'; import type { @@ -29,7 +29,7 @@ export function validateEncoderInput( if (!validationResult.success) { return { ...defaultEncoderInput, inputText, inputEncoding, outputEncoding, validationResult }; } - inputText = validationResult.value; + inputText = validationResult.value ?? ''; return createEncoderInput(inputText, inputEncoding, outputEncoding, validationResult); } @@ -72,7 +72,9 @@ function getEncodingParameters( ): EncoderInput { const bytes = stringToByteArray(inputText, inputEncoding); const ascii = inputEncoding === 'ascii' ? inputText : ''; - const utf8 = isTextEncoding(inputEncoding) ? getSimpleUtf8StringDecomposition(inputText) : null; + const utf8 = isTextEncoding(inputEncoding) + ? getSimpleUtf8StringDecomposition(inputText) + : defaultUtf8StringComposition; const binary = inputEncoding === 'bin' ? inputText : byteArrayToBinaryStringArray(bytes).join(''); const hex = hexStringFromByteArray(bytes, true, ' '); const hexBytes = hex.split(' '); @@ -94,6 +96,7 @@ function getEncodingParameters( totalChunks, lastChunkPadded, padLength, + chunks: [], }; } @@ -111,16 +114,22 @@ export function createHexByteMapsForChunk( byteStrings: string[], ): HexByteMap[] { return Array.from({ length: inputBytes.length }, (_, i) => { - const word1 = byteStrings[i].substring(0, 4); - const word2 = byteStrings[i].substring(4, 8); + const word1 = byteStrings?.[i]?.substring(0, 4) ?? ''; + const word2 = byteStrings?.[i]?.substring(4, 8) ?? ''; + const byte = inputBytes?.[i] ?? 0; + const char = String.fromCharCode(byte); return { - byte: inputBytes[i], + byte, bin_word1: word1, bin_word2: word2, - hex_word1: BIN_TO_HEX[word1], - hex_word2: BIN_TO_HEX[word2], - ascii: encoding === 'ascii' ? (/^\s+$/.test(ascii[i]) ? 'ws' : ascii[i]) : '', - isWhiteSpace: /^\s+$/.test(ascii[i]), + hex_word1: BIN_TO_HEX?.[word1] ?? '', + hex_word2: BIN_TO_HEX?.[word2] ?? '', + ascii: encoding === 'ascii' ? (/^\s+$/.test(ascii?.[i] ?? '') ? 'ws' : ascii?.[i] ?? '') : '', + char, + isWhiteSpace: /^\s+$/.test(char ?? ''), + groupId: ``, + bitGroups: [], + characterId: ``, }; }); } @@ -169,9 +178,11 @@ function getDecodingParameters( inputEncoding, validationResult, base64, + binary: '', totalChunks, lastChunkPadded, padLength, + chunks: [], }; } @@ -183,22 +194,26 @@ function createDecoderInputChunk( ): Base64ByteMap[] { const base64lookup = getBase64LookupMap(encoding); const base64Map = base64.split('').map((b64) => { - const dec = base64lookup[b64]; + const dec = base64lookup?.[b64] ?? 0; const bin = `${'0'.repeat(6 - dec.toString(2).length)}${dec.toString(2)}`; return { bin, dec, b64, isPad: false, + groupId: '', + bitGroups: [], }; }); if (isPadded) { Array.from({ length: padLength }, (_, i) => i).forEach(() => base64Map.push({ bin: '', - dec: null, + dec: 0, b64: '=', isPad: true, + groupId: '', + bitGroups: [], }), ); } diff --git a/apps/svelte-base64/src/lib/maps.ts b/apps/svelte-base64/src/lib/maps.ts index a6791ccc..32de90b3 100644 --- a/apps/svelte-base64/src/lib/maps.ts +++ b/apps/svelte-base64/src/lib/maps.ts @@ -3,7 +3,7 @@ import type { AsciiCharacterMap, Base64CharacterMap, Base64Encoding } from '$lib import { chunkify, decimalToBinaryString } from '$lib/util'; export const getBase64LookupMap = (base64Encoding: Base64Encoding): { [key: string]: number } => { - const base64Lookup = {}; + const base64Lookup: { [k: string]: number } = {}; getBase64Alphabet(base64Encoding).forEach((letter, index) => { base64Lookup[letter] = index; }); diff --git a/apps/svelte-base64/src/lib/unicode/api.ts b/apps/svelte-base64/src/lib/unicode/api.ts index 0fb2a423..db09790e 100644 --- a/apps/svelte-base64/src/lib/unicode/api.ts +++ b/apps/svelte-base64/src/lib/unicode/api.ts @@ -2,10 +2,10 @@ import { dev } from '$app/environment'; import { PUBLIC_API_BASE_URL } from '$env/static/public'; import type { HttpResponse, Result } from '$lib/types'; import { UnicodeCharInfoSchema, type FlattenedError, type UnicodeCharInfoParseResult } from '$lib/types/api'; +import { apiMocks } from '$lib/unicode/mocks'; import { COMPLEX_SYMBOL_REGEX } from '$lib/unicode/regex'; import { sleep, strictUriEncode } from '$lib/util'; import { z } from 'zod'; -import { apiMocks } from './mocks'; export async function getUnicodeCharInfo(s: string): Promise> { const fetchMethod = import.meta.env.MODE !== 'test' ? fetchUnicodeCharInfo : mockFetchUnicodeCharInfo; @@ -15,18 +15,18 @@ export async function getUnicodeCharInfo(s: string): Promise { await sleep(1); - return {success: true, data: apiMocks?.[strictUriEncode(utf8)] || []}; + return { success: true, data: apiMocks?.[strictUriEncode(utf8)] || [] }; } diff --git a/apps/svelte-base64/src/lib/unicode/mocks.ts b/apps/svelte-base64/src/lib/unicode/mocks.ts index db6f431d..6bf8f344 100644 --- a/apps/svelte-base64/src/lib/unicode/mocks.ts +++ b/apps/svelte-base64/src/lib/unicode/mocks.ts @@ -8,11 +8,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F9A6', block: 'Supplemental Symbols and Pictographs', plane: 'SMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🦦', '🦦'], uriEncoded: '%F0%9F%A6%A6', utf8: '0xF0 0x9F 0xA6 0xA6', utf8HexBytes: ['F0', '9F', 'A6', 'A6'], @@ -26,11 +21,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F468', block: 'Miscellaneous Symbols and Pictographs', plane: 'SMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['👨', '👨'], uriEncoded: '%F0%9F%91%A8', utf8: '0xF0 0x9F 0x91 0xA8', utf8HexBytes: ['F0', '9F', '91', 'A8'], @@ -42,11 +32,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+200D', block: 'General Punctuation', plane: 'BMP', - category: 'Format (Cf)', - bidirectionalClass: 'Boundary Neutral (BN)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['‍', '‍', '‍'], uriEncoded: '%E2%80%8D', utf8: '0xE2 0x80 0x8D', utf8HexBytes: ['E2', '80', '8D'], @@ -58,11 +43,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F33E', block: 'Miscellaneous Symbols and Pictographs', plane: 'SMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🌾', '🌾'], uriEncoded: '%F0%9F%8C%BE', utf8: '0xF0 0x9F 0x8C 0xBE', utf8HexBytes: ['F0', '9F', '8C', 'BE'], @@ -76,11 +56,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1FAE5', block: 'Symbols and Pictographs Extended-A', plane: 'SMP', - category: 'Unassigned (Cn)', - bidirectionalClass: '', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🫥', '🫥'], uriEncoded: '%F0%9F%AB%A5', utf8: '0xF0 0x9F 0xAB 0xA5', utf8HexBytes: ['F0', '9F', 'AB', 'A5'], @@ -94,11 +69,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F3C3', block: 'Miscellaneous Symbols and Pictographs', plane: 'SMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🏃', '🏃'], uriEncoded: '%F0%9F%8F%83', utf8: '0xF0 0x9F 0x8F 0x83', utf8HexBytes: ['F0', '9F', '8F', '83'], @@ -110,11 +80,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F3FF', block: 'Miscellaneous Symbols and Pictographs', plane: 'SMP', - category: 'Modifier Symbol (Sk)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🏿', '🏿'], uriEncoded: '%F0%9F%8F%BF', utf8: '0xF0 0x9F 0x8F 0xBF', utf8HexBytes: ['F0', '9F', '8F', 'BF'], @@ -126,11 +91,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+200D', block: 'General Punctuation', plane: 'BMP', - category: 'Format (Cf)', - bidirectionalClass: 'Boundary Neutral (BN)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['‍', '‍', '‍'], uriEncoded: '%E2%80%8D', utf8: '0xE2 0x80 0x8D', utf8HexBytes: ['E2', '80', '8D'], @@ -142,11 +102,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+2640', block: 'Miscellaneous Symbols', plane: 'BMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['♀', '♀', '♀'], uriEncoded: '%E2%99%80', utf8: '0xE2 0x99 0x80', utf8HexBytes: ['E2', '99', '80'], @@ -158,11 +113,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+FE0F', block: 'Variation Selectors', plane: 'BMP', - category: 'Nonspacing Mark (Mn)', - bidirectionalClass: 'Nonspacing Mark (NSM)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['️', '️'], uriEncoded: '%EF%B8%8F', utf8: '0xEF 0xB8 0x8F', utf8HexBytes: ['EF', 'B8', '8F'], @@ -176,11 +126,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+261D', block: 'Miscellaneous Symbols', plane: 'BMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['☝', '☝'], uriEncoded: '%E2%98%9D', utf8: '0xE2 0x98 0x9D', utf8HexBytes: ['E2', '98', '9D'], @@ -192,11 +137,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+1F3FE', block: 'Miscellaneous Symbols and Pictographs', plane: 'SMP', - category: 'Modifier Symbol (Sk)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['🏾', '🏾'], uriEncoded: '%F0%9F%8F%BE', utf8: '0xF0 0x9F 0x8F 0xBE', utf8HexBytes: ['F0', '9F', '8F', 'BE'], @@ -210,11 +150,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+2713', block: 'Dingbats', plane: 'BMP', - category: 'Other Symbol (So)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['✓', '✓', '✓'], uriEncoded: '%E2%9C%93', utf8: '0xE2 0x9C 0x93', utf8HexBytes: ['E2', '9C', '93'], @@ -228,11 +163,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0020', block: 'Basic Latin', plane: 'BMP', - category: 'Space Separator (Zs)', - bidirectionalClass: 'White Space (WS)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: [' ', ' '], uriEncoded: '%20', utf8: '0x20', utf8HexBytes: ['20'], @@ -246,11 +176,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+00E0', block: 'Latin-1 Supplement', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['à', 'à', 'à'], uriEncoded: '%C3%A0', utf8: '0xC3 0xA0', utf8HexBytes: ['C3', 'A0'], @@ -264,11 +189,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+006C', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['l', 'l'], uriEncoded: '%6C', utf8: '0x6C', utf8HexBytes: ['6C'], @@ -282,11 +202,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0061', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['a', 'a'], uriEncoded: '%61', utf8: '0x61', utf8HexBytes: ['61'], @@ -300,11 +215,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+006D', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['m', 'm'], uriEncoded: '%6D', utf8: '0x6D', utf8HexBytes: ['6D'], @@ -318,11 +228,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+006F', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['o', 'o'], uriEncoded: '%6F', utf8: '0x6F', utf8HexBytes: ['6F'], @@ -336,11 +241,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0064', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['d', 'd'], uriEncoded: '%64', utf8: '0x64', utf8HexBytes: ['64'], @@ -354,11 +254,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0065', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['e', 'e'], uriEncoded: '%65', utf8: '0x65', utf8HexBytes: ['65'], @@ -372,11 +267,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+2211', block: 'Mathematical Operators', plane: 'BMP', - category: 'Math Symbol (Sm)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: true, - htmlEntities: ['∑', '∑', '∑'], uriEncoded: '%E2%88%91', utf8: '0xE2 0x88 0x91', utf8HexBytes: ['E2', '88', '91'], @@ -390,11 +280,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+00DF', block: 'Latin-1 Supplement', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['ß', 'ß', 'ß'], uriEncoded: '%C3%9F', utf8: '0xC3 0x9F', utf8HexBytes: ['C3', '9F'], @@ -408,11 +293,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+00E5', block: 'Latin-1 Supplement', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['å', 'å', 'å'], uriEncoded: '%C3%A5', utf8: '0xC3 0xA5', utf8HexBytes: ['C3', 'A5'], @@ -426,11 +306,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0153', block: 'Latin Extended-A', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['œ', 'œ', 'œ'], uriEncoded: '%C5%93', utf8: '0xC5 0x93', utf8HexBytes: ['C5', '93'], @@ -444,11 +319,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+2248', block: 'Mathematical Operators', plane: 'BMP', - category: 'Math Symbol (Sm)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: true, - htmlEntities: ['≈', '≈', '≈'], uriEncoded: '%E2%89%88', utf8: '0xE2 0x89 0x88', utf8HexBytes: ['E2', '89', '88'], @@ -462,11 +332,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+2206', block: 'Mathematical Operators', plane: 'BMP', - category: 'Math Symbol (Sm)', - bidirectionalClass: 'Other Neutral (ON)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['∆', '∆'], uriEncoded: '%E2%88%86', utf8: '0xE2 0x88 0x86', utf8HexBytes: ['E2', '88', '86'], @@ -480,11 +345,6 @@ export const apiMocks: { [k: string]: UnicodeCharInfo[] } = { codepoint: 'U+0063', block: 'Basic Latin', plane: 'BMP', - category: 'Lowercase Letter (Ll)', - bidirectionalClass: 'Left To Right (L)', - combiningClass: 'Not Reordered (0)', - isMirrored: false, - htmlEntities: ['c', 'c'], uriEncoded: '%63', utf8: '0x63', utf8HexBytes: ['63'], diff --git a/apps/svelte-base64/src/lib/unicode/utf8.ts b/apps/svelte-base64/src/lib/unicode/utf8.ts index 64d3c20f..1056209e 100644 --- a/apps/svelte-base64/src/lib/unicode/utf8.ts +++ b/apps/svelte-base64/src/lib/unicode/utf8.ts @@ -24,10 +24,10 @@ const isUnihanChar = (charData: UnicodeCharInfo): boolean => export async function getUtf8StringDecomposition(s: string): Promise { const result = await getFullUtf8StringDecomposition(s); - if (!result.success && result.error) { - const { formErrors, fieldErrors } = result.error; - console.log({ formErrors, fieldErrors }); - } + // if (result.error) { + // const { formErrors, fieldErrors } = result.error; + // console.log({ formErrors, fieldErrors }); + // } return result.success && result.value ? result.value : getSimpleUtf8StringDecomposition(s); } @@ -80,6 +80,7 @@ async function getFullUtf8StringDecomposition(s: string): Promise charMap.encoded).join(''), totalBytes: bytes.length, hexBytes: complexCharMap.map((charMap) => charMap.hexBytes).flat(), + hexMap: [], bytes, charMap: complexCharMap, }; @@ -90,19 +91,24 @@ export function getSimpleUtf8StringDecomposition(s: string): Utf8StringCompositi const complexCharMap: Utf8ComplexCharacterMap[] | undefined = s.match(COMPLEX_SYMBOL_REGEX)?.map((utf8) => { const charMap: Utf8StandardCharacterMap[] = [...utf8].map((char) => { const charData = getUtf8EncodedByteMaps(char).map((byteMap) => ({ hex: byteMap.hex, byte: byteMap.byte })); + const hexBytes = charData.map((data) => data.hex); const bytes = charData.map((data) => data.byte); - const totalBytes = bytes.length; - const codepoints = totalBytes <= 4 ? unicodeCodepointFromUtf8ByteArray(bytes) : null; - const decimalCodepoint = codepoints?.dec; + + let codepoints = { hex: '', dec: 0 }; + const result = unicodeCodepointFromUtf8ByteArray(bytes); + if (result.success) { + codepoints = result.value ?? { hex: '', dec: 0 }; + } + return { char, isCombined: false, isASCII: validateAsciiBytes(bytes), - hexBytes: charData.map((data) => data.hex), + hexBytes, bytes, - codepoint: codepoints?.hex ?? "", - decimalCodepoint, - totalBytes, + codepoint: codepoints.hex, + decimalCodepoint: codepoints.dec, + totalBytes: bytes.length, encoded: strictUriEncode(char), }; }); @@ -132,6 +138,7 @@ export function getSimpleUtf8StringDecomposition(s: string): Utf8StringCompositi encoded: strictUriEncode(s), totalBytes: bytes?.length ?? 0, hexBytes: complexCharMap?.map((charMap) => charMap.hexBytes).flat() ?? [], + hexMap: [], bytes: bytes ?? [], charMap: complexCharMap ?? [], }; @@ -140,19 +147,20 @@ export function getSimpleUtf8StringDecomposition(s: string): Utf8StringCompositi export function getUtf8EncodedByteMaps(s: string): ByteEncodingMap[] { const utf8Encoded = strictUriEncode(s); const utf8ByteMaps = getUtf8ByteMaps(utf8Encoded); - const asciiByteMaps: ByteEncodingMap[] = utf8ByteMaps.length - ? findMissingAsciiBytes(utf8ByteMaps, utf8Encoded) - : getAsciiByteMaps(utf8Encoded, 0, utf8Encoded.length); + const asciiByteMaps: ByteEncodingMap[] = + utf8ByteMaps.length > 0 + ? findMissingAsciiBytes(utf8ByteMaps, utf8Encoded) + : getAsciiByteMaps(utf8Encoded, 0, utf8Encoded.length); return [...utf8ByteMaps, ...asciiByteMaps].sort((a, b) => a.start - b.start); } function getUtf8ByteMaps(utf8Encoded: string): ByteEncodingMap[] { const encodedUtf8Bytes = [...utf8Encoded.matchAll(/%(?[0-9A-F]{2,2})/g)]; return encodedUtf8Bytes.map((match) => ({ - byte: hexStringToByte(match.groups?.encodedByte ?? "0"), - hex: match.groups?.encodedByte ?? "", + byte: hexStringToByte(match.groups?.encodedByte ?? '0'), + hex: match.groups?.encodedByte ?? '', start: match.index ?? 0, - end: match.index ?? 0 + match[0].length, + end: (match.index ?? 0) + match[0].length, })); } @@ -180,6 +188,6 @@ function getAsciiByteMaps(utf8Encoded: string, start: number, end: number): Byte hex: hexStringFromByte(byte), start: start + i, end: start + i + 1, - })) + })) : []; } diff --git a/apps/svelte-base64/src/lib/util.ts b/apps/svelte-base64/src/lib/util.ts index 85cc715e..5b18d62f 100644 --- a/apps/svelte-base64/src/lib/util.ts +++ b/apps/svelte-base64/src/lib/util.ts @@ -1,3 +1,4 @@ +import { browser } from '$app/environment'; import type { BitGroupDetails, Result, StringEncoding } from '$lib/types'; import { getSimpleUtf8StringDecomposition } from '$lib/unicode/utf8'; import { validateAsciiBytes } from '$lib/validation'; @@ -13,10 +14,10 @@ export const stringToByteArray = (s: string, encoding: StringEncoding): number[] encoding === 'hex' ? hexStringToByteArray(s) : encoding === 'bin' - ? binaryStringToByteArray(s) - : encoding === 'utf8' - ? utf8StringToByteArray(s) - : genericStringToByteArray(s); + ? binaryStringToByteArray(s) + : encoding === 'utf8' + ? utf8StringToByteArray(s) + : genericStringToByteArray(s); export const hexStringToByte = (hex: string): number => parseInt(hex, 16); @@ -34,11 +35,11 @@ export const genericStringToByteArray = (s: string): number[] => export const asciiStringFromByteArray = (byteArray: number[]): string => validateAsciiBytes(byteArray) ? Array.from(byteArray, (x) => String.fromCharCode(x)).join('') : ''; -export const hexStringFromByte = (byte: number, upperCase = true): string => - upperCase ? byte.toString(16).toUpperCase().padStart(2, '0') : byte.toString(16).padStart(2, '0'); +export const hexStringFromByte = (byte: number, minLength = 2, upperCase = true): string => + upperCase ? byte.toString(16).toUpperCase().padStart(minLength, '0') : byte.toString(16).padStart(minLength, '0'); export const hexStringFromByteArray = (byteArray: number[], upperCase = false, separator = ''): string => - byteArray.map((byte) => hexStringFromByte(byte, upperCase)).join(separator); + byteArray.map((byte) => hexStringFromByte(byte, 2, upperCase)).join(separator); export const byteArrayToBinaryStringArray = (byteArray: number[]): string[] => byteArray.map((byte) => decimalToBinaryString(byte)); @@ -60,29 +61,65 @@ export function utf8StringFromByteArray(byteArray: number[]): string { } } -export function unicodeCodepointFromUtf8ByteArray(byteArray: number[]): { hex: string; dec: number } { - const [m, n, o, p] = [...byteArray]; - const codepointDecimal = - m < 0x80 - ? (m & 0x7f) << 0 - : 0xc1 < m && m < 0xe0 && n === (n & 0xbf) - ? ((m & 0x1f) << 6) | ((n & 0x3f) << 0) - : ((m === 0xe0 && 0x9f < n && n < 0xc0) || - (0xe0 < m && m < 0xed && 0x7f < n && n < 0xc0) || - (m === 0xed && 0x7f < n && n < 0xa0) || - (0xed < m && m < 0xf0 && 0x7f < n && n < 0xc0)) && - (o === o) & 0xbf - ? ((m & 0x0f) << 12) | ((n & 0x3f) << 6) | ((o & 0x3f) << 0) - : ((m === 0xf0 && 0x8f < n && n < 0xc0) || - (m === 0xf4 && 0x7f < n && n < 0x90) || - (0xf0 < m && m < 0xf4 && 0x7f < n && n < 0xc0)) && - (o === o) & 0xbf && - (p === p) & 0xbf - ? ((m & 0x07) << 18) | ((n & 0x3f) << 12) | ((o & 0x3f) << 6) | ((p & 0x3f) << 0) - : (() => { - throw 'Invalid UTF-8 encoding!'; - })(); - return { hex: `U+${hexStringFromByte(codepointDecimal)}`, dec: codepointDecimal }; +export function unicodeCodepointFromUtf8ByteArray(byteArray: number[]): Result<{ hex: string; dec: number }> { + if (!validateUtf8Bytes(byteArray)) { + return { success: false, error: Error('Invalid UTF-8 byte sequence') }; + } + const utf32 = utf8ByteArrayToUtf32Byte(byteArray); + return { success: true, value: { hex: `U+${hexStringFromByte(utf32, 4)}`, dec: utf32 } }; +} + +function validateUtf8Bytes(byteArray: number[]): boolean { + const [firstByte, ...remainingBytes] = byteArray; + if (!firstByte) { + return false; + } + const expectedByteCount = validateFirstUtf8Byte(firstByte); + if (expectedByteCount === 0) { + return false; + } + if (byteArray.length !== expectedByteCount) { + return false; + } + return expectedByteCount === 1 ? true : remainingBytes.every((byte) => (byte & 0xc0) === 0x80); +} + +function validateFirstUtf8Byte(byte: number): number { + if ((byte & 0x80) === 0x00) { + return 1; + } + if ((byte & 0xe0) === 0xc0) { + return 2; + } + if ((byte & 0xf0) === 0xe0) { + return 3; + } + if ((byte & 0xf8) === 0xf0) { + return 4; + } + return 0; +} + +function utf8ByteArrayToUtf32Byte(byteArray: number[]): number { + switch (byteArray.length) { + case 1: + return byteArray[0] ? byteArray[0] & 0x7f : 0; + case 2: + return byteArray[0] && byteArray[1] ? ((byteArray[0] & 0x1f) << 6) | (byteArray[1] & 0x3f) : 0; + case 3: + return byteArray[0] && byteArray[1] && byteArray[2] + ? ((byteArray[0] & 0x0f) << 12) | ((byteArray[1] & 0x3f) << 6) | (byteArray[2] & 0x3f) + : 0; + case 4: + return byteArray[0] && byteArray[1] && byteArray[2] && byteArray[3] + ? ((byteArray[0] & 0x07) << 18) | + ((byteArray[1] & 0x3f) << 12) | + ((byteArray[2] & 0x3f) << 6) | + (byteArray[3] & 0x3f) + : 0; + default: + return 0; + } } export function chunkify(args: { inputList: T[]; chunkSize: number }): T[][] { @@ -98,8 +135,8 @@ export const getCSSPropValue = (element: HTMLElement, propName: string): string getComputedStyle(element).getPropertyValue(propName); export function clickOutside(node: HTMLElement, { enabled: initialEnabled, cb }: { enabled: boolean; cb: () => void }) { - const handleOutsideClick = ({ target }) => { - if (!node.contains(target)) { + const handleOutsideClick = ({ target }: MouseEvent) => { + if (target instanceof Node && !node.contains(target)) { cb(); } }; @@ -121,46 +158,41 @@ export function clickOutside(node: HTMLElement, { enabled: initialEnabled, cb }: }; } -export const getRandomHexString = (length: number): string => - Array.from({ length }, () => Math.floor(Math.random() * 16)) - .map((n) => Number(n).toString(16)) - .join(''); - export function parseGroupId(groupId: string): BitGroupDetails { let match = HEX_BIT_GROUP_REGEX.exec(groupId); if (match) { - const { chunk, byte } = match.groups; - const chunkIndex = parseInt(chunk) - 1; - const byteIndexWithinChunk = parseInt(byte) - 1; + const [_, chunk, byte] = match; + const chunkIndex = parseInt(chunk ?? '0') - 1; + const byteIndexWithinChunk = parseInt(byte ?? '0') - 1; const byteIndex = chunkIndex * 3 + byteIndexWithinChunk; return { chunkIndex, byteIndex, byteIndexWithinChunk, - b64CharIndex: null, - b64IndexWithinChunk: null, + b64CharIndex: 0, + b64IndexWithinChunk: 0, }; } match = B64_BIT_GROUP_REGEX.exec(groupId); if (match) { - const { chunk, b64Char } = match.groups; - const chunkIndex = parseInt(chunk) - 1; - const b64IndexWithinChunk = parseInt(b64Char) - 1; + const [_, chunk, b64Char] = match; + const chunkIndex = parseInt(chunk ?? '0') - 1; + const b64IndexWithinChunk = parseInt(b64Char ?? '0') - 1; const b64CharIndex = chunkIndex * 4 + b64IndexWithinChunk; return { chunkIndex, - byteIndex: null, - byteIndexWithinChunk: null, + byteIndex: 0, + byteIndexWithinChunk: 0, b64CharIndex, b64IndexWithinChunk, }; } return { - chunkIndex: null, - byteIndex: null, - byteIndexWithinChunk: null, - b64CharIndex: null, - b64IndexWithinChunk: null, + chunkIndex: 0, + byteIndex: 0, + byteIndexWithinChunk: 0, + b64CharIndex: 0, + b64IndexWithinChunk: 0, }; } @@ -179,7 +211,7 @@ export const getChunkIndexFromBase64CharIndex = (charIndex: number): number => ( /* c8 ignore start */ export async function copyToClipboard(text: string): Promise { - if (typeof window !== 'undefined') { + if (browser) { try { await navigator.clipboard.writeText(text); return { success: true }; @@ -187,5 +219,9 @@ export async function copyToClipboard(text: string): Promise { return { success: false, error: Error('Error! Failed to copy text to clipboard.') }; } } + return { + success: false, + error: Error('This function (copyToClipboard) must be run in browser (client-side)'), + }; } /* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/validation.ts b/apps/svelte-base64/src/lib/validation.ts index 5312c01b..9d38a8c3 100644 --- a/apps/svelte-base64/src/lib/validation.ts +++ b/apps/svelte-base64/src/lib/validation.ts @@ -11,6 +11,17 @@ const BASE64_URL_FORMAT = /^[0-9A-Za-z-_]+[=]{0,2}$/; export const validateAsciiBytes = (byteArray: number[]): boolean => byteArray?.every((byte: number) => byte > 31 && byte < 127); +const charCodeIsWhitespace = (byte: number): boolean => /\s/.test(String.fromCharCode(byte)); + +const getStringRepresentationOfCharCode = (byte: number): string => + charCodeIsWhitespace(byte) ? `' '` : String.fromCharCode(byte); + +const getInvalidCharReport = (details: { byte: number; count: number }): string => + `\t${getStringRepresentationOfCharCode(details.byte)} (0x${details.byte + .toString(16) + .toUpperCase() + .padStart(2, '0')}) Count: ${details.count}`; + export function checkAllTextEncodings(input: string): string[] { const validEncodings: string[] = []; if (validateBinaryString(input).success) { @@ -48,9 +59,8 @@ export function validateTextEncoding(input: string, encoding: StringEncoding): R function validateAsciiString(input: string): Result { if (!/^[ -~]+$/.test(input)) { const nonAsciiChars = getNonAsciiCharsFromString(input); - const error = `'${input}' contains ${nonAsciiChars.length} invalid character${ - nonAsciiChars.length > 1 ? 's' : '' - }:\n${nonAsciiChars.join('\n')}`; + const plural = nonAsciiChars.length > 1 ? 'characters' : 'character'; + const error = `'${input}' contains ${nonAsciiChars.length} invalid ${plural}:\n${nonAsciiChars.join('\n')}`; return { success: false, error: Error(error) }; } return { success: true, value: input }; @@ -63,17 +73,6 @@ function getNonAsciiCharsFromString(input: string): string[] { return byteCounts.sort((a, b) => b.count - a.count).map(getInvalidCharReport); } -const charCodeIsWhitespace = (byte: number): boolean => /\s/.test(String.fromCharCode(byte)); - -const getStringRepresentationOfCharCode = (byte: number): string => - charCodeIsWhitespace(byte) ? `' '` : String.fromCharCode(byte); - -const getInvalidCharReport = (details: { byte: number; count: number }): string => - `\t${getStringRepresentationOfCharCode(details.byte)} (0x${details.byte - .toString(16) - .toUpperCase() - .padStart(2, '0')}) Count: ${details.count}`; - function validateHexString(input: string): Result { const originalInput = input; input = input?.replace(/ /g, ''); @@ -109,9 +108,12 @@ export function validateUtf8String(input: string): Result { if (roundtrip === input) { return { success: true, value: input }; } - } catch (ex: unknown) { - return { success: false, error: Error(`Error occurred when encoding URI component: ${input}\n${ex.toString()}`) }; + } catch (error: unknown) { + if (error instanceof Error) { + return { success: false, error: Error(`Error occurred when encoding URI component: ${input}\n${error.message}`) }; + } } + return { success: false, error: Error(`"${input}" is not a valid UTF-8 string.`) }; } export function validateBase64Encoding(input: string, encoding: Base64Encoding): Result { diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.ts index ab5d00b2..a7e9715a 100644 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.ts +++ b/apps/svelte-base64/src/lib/xstate/b64Encode.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { b64Encode } from '$lib/base64'; import { defaultBase64ByteMap, @@ -1328,7 +1327,7 @@ export const encodingMachine = stopAutoPlay: assign({ autoplay: (_) => false }), setFlagSkipDemo: assign({ skipDemo: (_) => true }), validate: assign({ - input: (_: EncodingContext, event: EncodingEvent) => { + input: (context: EncodingContext, event: EncodingEvent) => { if ( event.type === 'VALIDATE_TEXT' || event.type === 'UPDATE_TEXT' || @@ -1337,27 +1336,29 @@ export const encodingMachine = ) { return validateEncoderInput(event.inputText, event.inputEncoding, event.outputEncoding); } + return context.input; }, }), encode: assign({ inputChunkIndex: 0, - remainingInputChunks: (context: EncodingContext) => context.input.totalChunks, + remainingInputChunks: (context: EncodingContext) => context.input.totalChunks ?? 0, output: (context: EncodingContext) => { if (context.input.validationResult.success) { return b64Encode(context.input); } + return context.output; }, }), getCurrentByte: assign({ - currentByte: (context: EncodingContext) => context.byteMaps[context.byteIndex], + currentByte: (context: EncodingContext) => context.byteMaps[context.byteIndex] ?? defaultHexByteMap, updatedByteMaps: (context: EncodingContext) => context.byteMaps.slice(0, context.byteIndex + 1), }), generateByteMaps: assign({ byteMaps: (context: EncodingContext) => { if (isTextEncoding(context.input.inputEncoding)) { - return context.output.utf8.hexMap; + return context.output.utf8?.hexMap ?? []; } else { - return context.input.chunks.map((chunk) => chunk.inputMap.map((map) => map)).flat(); + return context.input.chunks?.map((chunk) => chunk.inputMap.map((map) => map)).flat() ?? []; } }, updatedByteMaps: (_) => [], @@ -1381,17 +1382,21 @@ export const encodingMachine = remainingBytes: (context: EncodingContext) => context.remainingBytes + 1, }), getCurrentInputChunk: assign({ - currentInputChunk: (context: EncodingContext) => context.input.chunks[context.inputChunkIndex], - updatedInputChunks: (context: EncodingContext) => context.input.chunks.slice(0, context.inputChunkIndex + 1), + currentInputChunk: (context: EncodingContext) => + context.input.chunks?.[context.inputChunkIndex] ?? defaultEncoderInputChunk, + updatedInputChunks: (context: EncodingContext) => + context.input.chunks?.slice(0, context.inputChunkIndex + 1) ?? [], }), resetRemainingInputChunks: assign({ updatedInputChunks: (_) => [], inputChunkIndex: (_) => 0, currentInputChunk: (_) => defaultEncoderInputChunk, - remainingInputChunks: (context: EncodingContext) => context.input.totalChunks - 1, + remainingInputChunks: (context: EncodingContext) => + context.input.totalChunks ? context.input.totalChunks - 1 : 0, }), resetNoInputChunksRemaining: assign({ - inputChunkIndex: (context: EncodingContext) => context.input.totalChunks - 1, + inputChunkIndex: (context: EncodingContext) => + context.input.totalChunks ? context.input.totalChunks - 1 : 0, remainingInputChunks: (_) => 0, }), mapNextInputChunk: assign({ @@ -1403,7 +1408,8 @@ export const encodingMachine = remainingInputChunks: (context: EncodingContext) => context.remainingInputChunks + 1, }), getCurrentOutputChunk: assign({ - currentOutputChunk: (context: EncodingContext) => context.output.chunks[context.outputChunkIndex], + currentOutputChunk: (context: EncodingContext) => + context.output.chunks?.[context.outputChunkIndex] ?? defaultOutputChunk, updatedOutputChunks: (context: EncodingContext) => context.output.chunks.slice(0, context.outputChunkIndex + 1), }), @@ -1411,10 +1417,12 @@ export const encodingMachine = updatedOutputChunks: (_) => [], outputChunkIndex: (_) => 0, currentOutputChunk: (_) => defaultOutputChunk, - remainingOutputChunks: (context: EncodingContext) => context.input.totalChunks - 1, + remainingOutputChunks: (context: EncodingContext) => + context.input.totalChunks ? context.input.totalChunks - 1 : 0, }), resetNoOutputChunksRemaining: assign({ - outputChunkIndex: (context: EncodingContext) => context.input.totalChunks - 1, + outputChunkIndex: (context: EncodingContext) => + context.input.totalChunks ? context.input.totalChunks - 1 : 0, remainingOutputChunks: (_) => 0, }), mapNextOutputChunk: assign({ @@ -1426,7 +1434,8 @@ export const encodingMachine = remainingOutputChunks: (context: EncodingContext) => context.remainingOutputChunks + 1, }), getCurrentBase64Char: assign({ - currentBase64Char: (context: EncodingContext) => context.base64Maps[context.base64CharIndex], + currentBase64Char: (context: EncodingContext) => + context.base64Maps?.[context.base64CharIndex] ?? defaultBase64ByteMap, updatedBase64Maps: (context: EncodingContext) => context.base64Maps.slice(0, context.base64CharIndex + 1), }), generateBase64Maps: assign({ @@ -1454,17 +1463,20 @@ export const encodingMachine = }), updateContextForLastStep: assign({ updatedByteMaps: (context: EncodingContext) => context.byteMaps.slice(0), - updatedInputChunks: (context: EncodingContext) => context.input.chunks.slice(0), + updatedInputChunks: (context: EncodingContext) => context.input.chunks?.slice(0) ?? [], updatedOutputChunks: (context: EncodingContext) => context.output.chunks.slice(0), updatedBase64Maps: (context: EncodingContext) => context.base64Maps.slice(0), byteIndex: (context: EncodingContext) => context.byteMaps.length - 1, - inputChunkIndex: (context: EncodingContext) => context.input.chunks.length - 1, + inputChunkIndex: (context: EncodingContext) => (context.input.chunks ? context.input.chunks.length - 1 : 0), outputChunkIndex: (context: EncodingContext) => context.output.chunks.length - 1, base64CharIndex: (context: EncodingContext) => context.base64Maps.length - 1, - currentByte: (context: EncodingContext) => context.byteMaps[context.byteMaps.length - 1], - currentInputChunk: (context: EncodingContext) => context.input.chunks[context.input.chunks.length - 1], - currentOutputChunk: (context: EncodingContext) => context.output.chunks[context.output.chunks.length - 1], - currentBase64Char: (context: EncodingContext) => context.base64Maps[context.base64Maps.length - 1], + currentByte: (context: EncodingContext) => context.byteMaps[context.byteMaps.length - 1] ?? defaultHexByteMap, + currentInputChunk: (context: EncodingContext) => + context.input.chunks?.[context.input.chunks.length - 1] ?? defaultEncoderInputChunk, + currentOutputChunk: (context: EncodingContext) => + context.output.chunks?.[context.output.chunks.length - 1] ?? defaultOutputChunk, + currentBase64Char: (context: EncodingContext) => + context.base64Maps[context.base64Maps.length - 1] ?? defaultBase64ByteMap, remainingInputChunks: (_) => 0, }), }, @@ -1484,11 +1496,11 @@ export const encodingMachine = hasPreviousByte: (context: EncodingContext) => context.byteIndex > 0, inputChunksRemaining: (context: EncodingContext) => context.input.lastChunkPadded ? context.remainingInputChunks > 1 : context.remainingInputChunks > 0, - lastChunkIsPadded: (context: EncodingContext) => !context.autoplay && context.input.lastChunkPadded, + lastChunkIsPadded: (context: EncodingContext) => (!context.autoplay && context.input.lastChunkPadded) || false, finalPaddedInputChunkRemaining: (context: EncodingContext) => (context.remainingInputChunks === 1 && context.input.lastChunkPadded) || false, onlyOnePaddedChunk: (context: EncodingContext) => - context.input.totalChunks === 1 && context.input.lastChunkPadded, + (context.input.totalChunks === 1 && context.input.lastChunkPadded) || false, noInputChunksRemaining: (context: EncodingContext) => context.remainingInputChunks === 0, allInputChunksRemaining: (context: EncodingContext) => context.remainingInputChunks + 1 === context.input.totalChunks, diff --git a/apps/svelte-base64/src/routes/+error.svelte b/apps/svelte-base64/src/routes/+error.svelte index 8d4db0ee..044deeb6 100644 --- a/apps/svelte-base64/src/routes/+error.svelte +++ b/apps/svelte-base64/src/routes/+error.svelte @@ -1,8 +1,6 @@
diff --git a/apps/svelte-base64/src/service-worker.ts b/apps/svelte-base64/src/service-worker.ts index 462b21e7..7bb17822 100644 --- a/apps/svelte-base64/src/service-worker.ts +++ b/apps/svelte-base64/src/service-worker.ts @@ -1,5 +1,10 @@ +/// +/// +/// +/// + import { build, files, version } from '$service-worker'; -const worker = self as unknown as any; +const worker = self as unknown as ServiceWorkerGlobalScope; const FILES = `cache${version}`; const to_cache = build.concat(files); const staticAssets = new Set(to_cache); @@ -42,7 +47,7 @@ async function fetchAndCache(request: Request) { // listen for the fetch events worker.addEventListener('fetch', (event) => { if (event.request.url.indexOf('/characters/') !== -1) { - return false; + return; } if (event.request.method !== 'GET' || event.request.headers.has('range')) return; const url = new URL(event.request.url); From a72366179f5aed90d4bd2645e30cad7122ffb12d Mon Sep 17 00:00:00 2001 From: Aaron Luna Date: Sun, 28 Jan 2024 14:27:16 -0800 Subject: [PATCH 3/5] refactor(svelte-base64): :recycle: refactor help section references in AlgorithmDemo --- .../Sections/Base64References1.svelte | 7 ++- .../Sections/Base64References2.svelte | 7 ++- .../HelpDocs/Sections/_helpText.ts | 33 ++++++------- .../AlgorithmDemo/HelpDocs/Sections/index.ts | 37 +++++++++++++++ .../src/lib/types/HelpSection.ts | 47 ++++++++++++++++++- 5 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/index.ts diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References1.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References1.svelte index 13c0f1da..802a4bc2 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References1.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References1.svelte @@ -1,7 +1,6 @@
@@ -10,7 +9,7 @@

{title}

-
src:{url}
+
source:{url}
{#each description as text}

{@html text}

diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References2.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References2.svelte index 07e726e8..7e2f4c97 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References2.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/Base64References2.svelte @@ -1,7 +1,6 @@
@@ -10,7 +9,7 @@

{title}

-
src:{url}
+
source:{url}
{#each description as text}

{@html text}

diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/_helpText.ts b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/_helpText.ts index 55a720b2..bdedc3ab 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/_helpText.ts +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/_helpText.ts @@ -1,3 +1,5 @@ +import type { HelpSectionReference } from '$lib/types'; + export const whyBase641 = [ 'Many application-level protocols, such as those used for email and web access, are character-based.', 'Although these protocols exchange bytes, those bytes are assumed to be restricted to a limited set of characters that are printable or contain print instructions. Such characters use only the low-order 7 bits in each 8-bit byte.', @@ -78,19 +80,18 @@ export const base64OutputEncoding = [ 'By default, the Standard Base64 alphabet is used (base64 in the dropdown menu). Selecting base64url will use the Base64 URL/filename-safe alphabet.', ]; -export const references = [ - { - title: 'RFC 4648: The Base16, Base32, and Base64 Data Encodings', - url: 'https://datatracker.ietf.org/doc/html/rfc4648', - description: [ - 'RFC 4648 is the specification for Base64 encoding (also Base32 and Base16 encodings, but these are rarely used). This document defines the standard and URL-safe alphabets used in this demonstration, as well as the algorithm for encoding 8-bit bytes to 6-bit ASCII characters.', - ], - }, - { - title: 'Base64 (wikipedia.com)', - url: 'https://en.wikipedia.org/wiki/Base64', - description: [ - 'The wikipedia article for Base64 covers a much larger number of subjects than RFC 4648, including the use of Base64 encoding with UTF-7, OpenPGP, MIME, and several other examples of practical uses for Base64 encoding.', - ], - }, -]; +export const HelpReference1: HelpSectionReference = { + title: 'RFC 4648: The Base16, Base32, and Base64 Data Encodings', + url: 'https://datatracker.ietf.org/doc/html/rfc4648', + description: [ + 'RFC 4648 is the specification for Base64 encoding (also Base32 and Base16 encodings, but these are rarely used). This document defines the standard and URL-safe alphabets used in this demonstration, as well as the algorithm for encoding 8-bit bytes to 6-bit ASCII characters.', + ], +}; + +export const HelpReference2: HelpSectionReference = { + title: 'Base64 (wikipedia.com)', + url: 'https://en.wikipedia.org/wiki/Base64', + description: [ + 'The wikipedia article for Base64 covers a much larger number of subjects than RFC 4648, including the use of Base64 encoding with UTF-7, OpenPGP, MIME, and several other examples of practical uses for Base64 encoding.', + ], +}; diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/index.ts b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/index.ts new file mode 100644 index 00000000..6c69fad1 --- /dev/null +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/HelpDocs/Sections/index.ts @@ -0,0 +1,37 @@ +import Base64OutputEncoding from './Base64OutputEncoding.svelte'; +import Base64References1 from './Base64References1.svelte'; +import Base64References2 from './Base64References2.svelte'; +import Base64StandardAlphabet from './Base64StandardAlphabet.svelte'; +import Base64UrlAlphabet from './Base64UrlAlphabet.svelte'; +import KeyboardShortcuts from './KeyboardShortcuts.svelte'; +import NavButtons from './NavButtons.svelte'; +import StringInputEncoding1 from './StringInputEncoding1.svelte'; +import StringInputEncoding2 from './StringInputEncoding2.svelte'; +import StringInputEncodingAscii from './StringInputEncodingAscii.svelte'; +import StringInputEncodingBinary from './StringInputEncodingBinary.svelte'; +import StringInputEncodingHex from './StringInputEncodingHex.svelte'; +import StringInputEncodingUtf8 from './StringInputEncodingUTF8.svelte'; +import WhatIsBase64 from './WhatIsBase64.svelte'; +import WhatIsntBase64 from './WhatIsntBase64.svelte'; +import WhyBase641 from './WhyBase641.svelte'; +import WhyBase642 from './WhyBase642.svelte'; + +export { + Base64OutputEncoding, + Base64References1, + Base64References2, + Base64StandardAlphabet, + Base64UrlAlphabet, + KeyboardShortcuts, + NavButtons, + StringInputEncoding1, + StringInputEncoding2, + StringInputEncodingAscii, + StringInputEncodingBinary, + StringInputEncodingHex, + StringInputEncodingUtf8, + WhatIsBase64, + WhatIsntBase64, + WhyBase641, + WhyBase642, +}; diff --git a/apps/svelte-base64/src/lib/types/HelpSection.ts b/apps/svelte-base64/src/lib/types/HelpSection.ts index 858f1920..c81658a3 100644 --- a/apps/svelte-base64/src/lib/types/HelpSection.ts +++ b/apps/svelte-base64/src/lib/types/HelpSection.ts @@ -1,10 +1,53 @@ -import type { SvelteComponent } from 'svelte'; +import type { + Base64OutputEncoding, + Base64References1, + Base64References2, + Base64StandardAlphabet, + Base64UrlAlphabet, + KeyboardShortcuts, + NavButtons, + StringInputEncoding1, + StringInputEncoding2, + StringInputEncodingAscii, + StringInputEncodingBinary, + StringInputEncodingHex, + StringInputEncodingUtf8, + WhatIsBase64, + WhatIsntBase64, + WhyBase641, + WhyBase642, +} from '$lib/components/AlgorithmDemo/HelpDocs/Sections'; + +export type HelpSectionComponent = + | typeof WhyBase641 + | typeof WhyBase642 + | typeof WhatIsBase64 + | typeof WhatIsntBase64 + | typeof Base64StandardAlphabet + | typeof Base64UrlAlphabet + | typeof StringInputEncoding1 + | typeof StringInputEncoding2 + | typeof StringInputEncodingAscii + | typeof StringInputEncodingUtf8 + | typeof StringInputEncodingHex + | typeof StringInputEncodingBinary + | typeof Base64OutputEncoding + | typeof NavButtons + | typeof KeyboardShortcuts + | typeof Base64References1 + | typeof Base64References2; export interface HelpSection { index: number; id: string; title: string; - component: typeof SvelteComponent; + component: HelpSectionComponent; } export type HelpSectionMap = Record; + +export interface HelpSectionReference { + title: string; + url: string; + description: string[]; +} From 4be260553afc680fa97f9ceeabdfe49d3e8f6c86 Mon Sep 17 00:00:00 2001 From: Aaron Luna Date: Sun, 28 Jan 2024 15:07:54 -0800 Subject: [PATCH 4/5] test(svelte-base64): :white_check_mark: remove old e2e test implementation with playwright e2e tests --- apps/svelte-base64/package.json | 40 +- apps/svelte-base64/playwright.config.ts | 1 + .../src/lib/xstate/b64Encode.test/eventLog.ts | 60 - .../lib/xstate/b64Encode.test/testEvents.ts | 3113 ----------------- .../lib/xstate/b64Encode.test/testPaths.ts | 2827 --------------- .../b64Encode.test/testPathsPuppeteer.ts | 385 -- .../b64Encode.test/testScriptGenerator.ts | 181 - .../testScriptGeneratorPuppeteer.ts | 176 - .../xstate/b64Encode.test/testSetGenerator.ts | 30 - .../src/lib/xstate/b64Encode.test/types.ts | 69 - .../src/lib/xstate/b64Encode.test/util.ts | 252 -- ...algoDemoTester.ts => algorithmDemoPage.ts} | 2 +- apps/svelte-base64/tests/base64.test.ts | 2 +- apps/svelte-base64/tests/dataPrep.test.ts | 209 +- apps/svelte-base64/tests/e2e.test.ts | 734 ++-- 15 files changed, 579 insertions(+), 7502 deletions(-) delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/eventLog.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testEvents.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testPaths.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testPathsPuppeteer.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGenerator.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGeneratorPuppeteer.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/testSetGenerator.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/types.ts delete mode 100644 apps/svelte-base64/src/lib/xstate/b64Encode.test/util.ts rename apps/svelte-base64/tests/{algoDemoTester.ts => algorithmDemoPage.ts} (99%) diff --git a/apps/svelte-base64/package.json b/apps/svelte-base64/package.json index e0e96e08..65cfc336 100644 --- a/apps/svelte-base64/package.json +++ b/apps/svelte-base64/package.json @@ -30,49 +30,49 @@ }, "devDependencies": { "@commitlint/config-conventional": "^17.8.1", - "@playwright/test": "^1.40.1", + "@playwright/test": "^1.41.1", "@testing-library/dom": "^8.20.1", "@testing-library/jest-dom": "^5.17.0", "@testing-library/svelte": "^3.2.2", - "@testing-library/user-event": "^14.5.1", + "@testing-library/user-event": "^14.5.2", "@types/cookie": "^0.5.4", - "@types/node": "^18.19.3", + "@types/node": "^18.19.10", "@types/testing-library__jest-dom": "^5.14.9", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", "@vitest/coverage-v8": "^0.33.0", "@vitest/ui": "^0.33.0", "@xstate/cli": "^0.3.3", "@xstate/graph": "^1.4.2", "@xstate/test": "^0.5.1", - "autoprefixer": "^10.4.16", - "eslint": "^8.55.0", - "eslint-config-prettier": "^8.10.0", + "autoprefixer": "^10.4.17", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-svelte3": "^4.0.0", + "eslint-plugin-svelte": "^2.35.1", "jsdom": "^20.0.3", - "playwright": "^1.40.1", - "postcss": "^8.4.32", - "postcss-html": "^1.5.0", + "playwright": "^1.41.1", + "postcss": "^8.4.33", + "postcss-html": "^1.6.0", "postcss-load-config": "^4.0.2", - "prettier": "^2.8.8", - "prettier-plugin-svelte": "^2.10.1", - "svelte": "^3.59.2", - "svelte-check": "^3.6.2", - "svelte-icons": "^2.1.0", + "prettier": "^3.2.4", + "prettier-plugin-svelte": "^3.1.2", + "svelte": "^4.2.9", + "svelte-check": "^3.6.3", "tslib": "^2.6.2", "typescript": "^5.3.3", - "ws": "^8.15.1" + "ws": "^8.16.0" }, "type": "module", "dependencies": { "@a-luna/shared-ui": "workspace:*", "@sveltejs/adapter-node": "^1.3.1", - "@sveltejs/kit": "^1.30.3", + "@sveltejs/kit": "^2.5.0", + "@sveltejs/vite-plugin-svelte": "^3.0.1", "@xstate/inspect": "^0.7.1", "@xstate/svelte": "^2.1.0", "cssnano": "^5.1.15", - "vite": "^4.5.1", + "vite": "^5.0.12", "vitest": "^0.33.0", "xstate": "^4.38.3", "zod": "^3.22.4" diff --git a/apps/svelte-base64/playwright.config.ts b/apps/svelte-base64/playwright.config.ts index 4a3b26f7..01cafa72 100644 --- a/apps/svelte-base64/playwright.config.ts +++ b/apps/svelte-base64/playwright.config.ts @@ -4,6 +4,7 @@ const config: PlaywrightTestConfig = { forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, use: { + headless: false, trace: 'on-first-retry', }, projects: [ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/eventLog.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/eventLog.ts deleted file mode 100644 index 1236684b..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/eventLog.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* c8 ignore start */ -import type { EncodingMachineStateStore } from '$lib/types'; -import { createTestScript } from '$lib/xstate/b64Encode.test/testScriptGenerator'; -import type { - EventLogStore, - MachineEvent, - MachineLogs, - MachineState, - MachineTestStepData, -} from '$lib/xstate/b64Encode.test/types'; -import { createMachineTestStepData, reconcileEventAndStateLists } from '$lib/xstate/b64Encode.test/util'; -import { get, writable } from 'svelte/store'; - -export function createEventLogStore(machineState: EncodingMachineStateStore): EventLogStore { - const { subscribe, update } = writable({ events: [], states: [] }); - - function getCurrentState(): MachineState { - const currentState = get(machineState).value; - const state = typeof currentState === 'string' ? currentState : Object.keys(currentState)[0]; - const substate = typeof currentState === 'string' ? 'none' : Object.values(currentState)[0].toString(); - return { state, substate }; - } - - function add(event: MachineEvent) { - update((machineLog) => { - machineLog.events.push(event); - setTimeout(() => machineLog.states.push(getCurrentState()), 10); - return machineLog; - }); - } - - function entries(): MachineTestStepData[] { - let logs: MachineLogs; - const unsubscribe = subscribe((value) => (logs = value)); - unsubscribe(); - const reconciledlogs: MachineLogs = reconcileEventAndStateLists(logs.events, logs.states); - return createMachineTestStepData(reconciledlogs.events, reconciledlogs.states); - } - - function testScript(scriptName?: string, ignoreUpdateTextEvents?: boolean): string { - return createTestScript(entries(), scriptName ?? null, ignoreUpdateTextEvents ?? true); - } - - function clear() { - update((eventLog) => { - eventLog = { events: [], states: [] }; - return eventLog; - }); - } - - return { - subscribe, - update, - add, - entries, - testScript, - clear, - }; -} -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testEvents.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testEvents.ts deleted file mode 100644 index 6f507220..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testEvents.ts +++ /dev/null @@ -1,3113 +0,0 @@ -/* c8 ignore start */ -import type { TestFunctionInputData } from '$lib/xstate/b64Encode.test/types'; - -const asciiHappyPathEvents: TestFunctionInputData = { - scriptName: 'asciiHappyPath', - description: 'encode ascii string, execute all steps manually', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: 't', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'te', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'tes', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainPadCharacter', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'verifyResults', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const asciiHappyPathAutoplayEvents: TestFunctionInputData = { - scriptName: 'asciiHappyPathAutoplay', - description: 'encode ascii string, execute all steps with autoplay', - type: 'slow', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: 't', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'te', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'tes', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'START_AUTOPLAY', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'autoPlayEncodeByte', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'autoPlayEncodeByte', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'autoPlayEncodeByte', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'autoPlayEncodeByte', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createInputChunks', - substate: 'autoPlayIdle', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createInputChunks', - substate: 'autoPlayCreateInputChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createInputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'autoPlayIdle', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'autoPlayCreateOutputChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainPadCharacter', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'idle', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'encodeOutput', - substate: 'autoPlayEncodeBase64', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'verifyResults', - substate: 'none', - }, - }, - { - event: { - type: 'AUTOPLAYING', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const asciiHappyPathSkipDemoEvents: TestFunctionInputData = { - scriptName: 'asciiHappyPathSkipDemo', - description: 'encode ascii string, skip demo', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'SKIP_DEMO', - inputText: 'test', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const asciiValidationErrorEvents: TestFunctionInputData = { - scriptName: 'asciiValidationError', - description: 'encode ascii string, validation error', - type: 'fast', - events: [ - { - event: { - type: 'START_AUTOPLAY', - inputText: '', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'do§', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'SKIP_DEMO', - inputText: 'do§', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'do', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: 'dog', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: 'dog', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const asciiWithSymbolsEvents: TestFunctionInputData = { - scriptName: 'asciiWithSymbols', - description: 'encode ascii string, with symbol characters', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: 'test&^%#*&()', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: 'test&^%#*&()', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const hexHappyPathEvents: TestFunctionInputData = { - scriptName: 'hexHappyPath', - description: 'encode hex string, execute all steps manually', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: '0d47bc37af', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '0d47bc37af', - inputEncoding: 'hex', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '0d47bc37af', - inputEncoding: 'hex', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainPadCharacter', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'verifyResults', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const hexValidationErrorEvents: TestFunctionInputData = { - scriptName: 'hexValidationError', - description: 'encode hex string, validation error', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: '746573t', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '746573t', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '746573t', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '746573', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '74657', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '74657', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '746573', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '7465737', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '74657374', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '74657374', - inputEncoding: 'hex', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const binHappyPathEvents: TestFunctionInputData = { - scriptName: 'binHappyPath', - description: 'encode bin string, execute all steps manually', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: '01110100011001010111001101110100', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '01110100011001010111001101110100', - inputEncoding: 'bin', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '01110100011001010111001101110100', - inputEncoding: 'bin', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainPadCharacter', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'verifyResults', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const binHappyPathSkipDemoEvents: TestFunctionInputData = { - scriptName: 'binHappyPathSkipDemo', - description: 'encode bin string, skip demo', - type: 'fast', - events: [ - { - event: { - type: 'SKIP_DEMO', - inputText: '01110100011001010111001101110100', - inputEncoding: 'ascii', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const binValidationErrorEvents: TestFunctionInputData = { - scriptName: 'binValidationError', - description: 'encode bin string, validation error', - type: 'fast', - events: [ - { - event: { - type: 'START_AUTOPLAY', - inputText: 'test', - inputEncoding: 'bin', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'SKIP_DEMO', - inputText: '0101', - inputEncoding: 'bin', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'error', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '01110100011001010111001101110100', - inputEncoding: 'bin', - outputEncoding: 'base64url', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const utf8HappyPathEvents: TestFunctionInputData = { - scriptName: 'utf8HappyPath', - description: 'encode utf8 string, execute all steps manually', - type: 'fast', - events: [ - { - event: { - type: 'UPDATE_TEXT', - inputText: '🦦👨‍🌾🫥🏃🏿‍♀️☝🏾', - inputEncoding: 'ascii', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'UPDATE_TEXT', - inputText: '🦦👨‍🌾🫥🏃🏿‍♀️☝🏾', - inputEncoding: 'utf8', - outputEncoding: 'base64', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '🦦👨‍🌾🫥🏃🏿‍♀️☝🏾', - inputEncoding: 'utf8', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'encodeByte', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeInput', - substate: 'explainByteMapping', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createInputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createInputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'regularIdle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createOutputChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'explainPadCharacter', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'createOutputChunks', - substate: 'createLastPaddedChunk', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'idle', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'encodeOutput', - substate: 'encodeBase64', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'verifyResults', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_NEXT_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -const utf8MixedAsciiEvents: TestFunctionInputData = { - scriptName: 'utf8MixedAscii', - description: 'encode multiple utf8 strings, mix of ascii and utf8', - type: 'fast', - events: [ - { - event: { - type: 'VALIDATE_TEXT', - inputText: '✓ à la mode', - inputEncoding: 'utf8', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_FIRST_STEP', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '∑ßåœ ≈ ∆c', - inputEncoding: 'utf8', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - { - event: { - type: 'GO_TO_FIRST_STEP', - }, - expectedState: { - state: 'inactive', - substate: 'none', - }, - }, - { - event: { - type: 'VALIDATE_TEXT', - inputText: '日本語文字列', - inputEncoding: 'utf8', - outputEncoding: 'base64', - }, - expectedState: { - state: 'validateInputText', - substate: 'success', - }, - }, - { - event: { - type: 'GO_TO_LAST_STEP', - }, - expectedState: { - state: 'finished', - substate: 'none', - }, - }, - ], -}; - -// const utf8ValidationErrorEvents: TestFunctionInputData = { -// scriptName: 'utf8ValidationError', -// description: 'encode utf8 string, validation error', -// type: 'fast', -// events: [ -// ], -// }; - -export const testScriptEvents = [ - asciiHappyPathEvents, - asciiHappyPathAutoplayEvents, - asciiHappyPathSkipDemoEvents, - asciiValidationErrorEvents, - asciiWithSymbolsEvents, - hexHappyPathEvents, - hexValidationErrorEvents, - binHappyPathEvents, - binHappyPathSkipDemoEvents, - binValidationErrorEvents, - utf8HappyPathEvents, - utf8MixedAsciiEvents, -]; -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPaths.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPaths.ts deleted file mode 100644 index 9ce63d83..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPaths.ts +++ /dev/null @@ -1,2827 +0,0 @@ -/* eslint-disable */ -/* c8 ignore start */ -import type { JSDomTestCase, JSDomTestFunction } from '$lib/xstate/b64Encode.test/types'; -import type { Screen } from '@testing-library/svelte'; -import type UserEvent from '@testing-library/user-event'; - -const asciiHappyPath: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: test - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'test'); - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createInputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The chunk size of 24-bits was chosen because it is divisible by 6`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` and final chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createOutputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Next, for each chunk of input data with 24 bits (three 8-bit bytes)`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Since the final input chunk contains only `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainPadCharacter after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainPadCharacter"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The final step is to convert each 6-bit value to the corresponding Base64 digit.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: verifyResults after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="verifyResults"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The input data has been successfully encoded as a string of Base64 characters!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: finished after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const asciiHappyPathAutoplay: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: test - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'test'); - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click RESUME_AUTO_PLAY button - const startAutoplayButton = await screen.findByTestId('start-autoplay-button'); - await userEvent.click(startAutoplayButton); - // Verify transition to state: validateInputText-success after event START_AUTOPLAY - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-idle - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-autoPlayEncodeByte - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="autoPlayEncodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-autoPlayEncodeByte - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="autoPlayEncodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-autoPlayEncodeByte - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="autoPlayEncodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-autoPlayEncodeByte - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="autoPlayEncodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeInput-explainByteMapping - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createInputChunks-autoPlayIdle - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="createInputChunks"][data-sub-state="autoPlayIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createInputChunks-autoPlayCreateInputChunk - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="autoPlayCreateInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createInputChunks-explainLastPaddedChunk - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The chunk size of 24-bits was chosen because it is divisible by 6`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createInputChunks-createLastPaddedChunk - await new Promise((r) => setTimeout(r, 200)); - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` and final chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createOutputChunks-autoPlayIdle - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="createOutputChunks"][data-sub-state="autoPlayIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Next, for each chunk of input data with three 8-bit bytes`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createOutputChunks-autoPlayCreateOutputChunk - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="autoPlayCreateOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createOutputChunks-explainLastPaddedChunk - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Since the final input chunk contains only `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createOutputChunks-explainPadCharacter - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainPadCharacter"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: createOutputChunks-createLastPaddedChunk - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-idle - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The final step is to convert each 6-bit value to the corresponding Base64 digit.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector( - '[data-state="encodeOutput"][data-sub-state="autoPlayEncodeBase64"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: verifyResults - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="verifyResults"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The input data has been successfully encoded as a string of Base64 characters!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Verify machine automatically transitions to next state: finished - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const asciiHappyPathSkipDemo: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: test - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'test'); - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event SKIP_DEMO - const domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - const expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const asciiValidationError: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click RESUME_AUTO_PLAY button - const startAutoplayButton = await screen.findByTestId('start-autoplay-button'); - await userEvent.click(startAutoplayButton); - // Verify transition to state: validateInputText-error after event START_AUTOPLAY - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: do§ - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'do§'); - // Change input encoding setting to ASCII - await userEvent.click(stringEncodingMenu); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: validateInputText-error after event SKIP_DEMO - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: dog - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, 'dog'); - // Change input encoding setting to ASCII - await userEvent.click(stringEncodingMenu); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const asciiWithSymbols: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: test&^%#*&() - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'test&^%#*&()'); - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const hexHappyPath: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: 0d47bc37af - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '0d47bc37af'); - // Change input encoding setting to hex - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const hexEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-3'); - await userEvent.click(hexEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createInputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The chunk size of 24-bits was chosen because it is divisible by 6`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` and final chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createOutputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Next, for each chunk of input data with 24 bits (three 8-bit bytes)`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Since the final input chunk contains only `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainPadCharacter after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainPadCharacter"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The final step is to convert each 6-bit value to the corresponding Base64 digit.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: verifyResults after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="verifyResults"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The input data has been successfully encoded as a string of Base64 characters!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: finished after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const hexValidationError: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: 746573t - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '746573t'); - // Change input encoding setting to hex - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const hexEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-3'); - await userEvent.click(hexEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-error after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: 74657 - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '74657'); - // Change input encoding setting to hex - await userEvent.click(stringEncodingMenu); - await userEvent.click(hexEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-error after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: 74657374 - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '74657374'); - // Change input encoding setting to hex - await userEvent.click(stringEncodingMenu); - await userEvent.click(hexEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const binHappyPath: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: 01110100011001010111001101110100 - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '01110100011001010111001101110100'); - // Change input encoding setting to bin - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const binEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-4'); - await userEvent.click(binEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createInputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The chunk size of 24-bits was chosen because it is divisible by 6`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` and final chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createOutputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Next, for each chunk of input data with 24 bits (three 8-bit bytes)`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Since the final input chunk contains only `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainPadCharacter after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainPadCharacter"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The final step is to convert each 6-bit value to the corresponding Base64 digit.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: verifyResults after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="verifyResults"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The input data has been successfully encoded as a string of Base64 characters!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: finished after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const binHappyPathSkipDemo: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: 01110100011001010111001101110100 - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '01110100011001010111001101110100'); - // Change input encoding setting to ASCII - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-1'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event SKIP_DEMO - const domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - const expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const binValidationError: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: test - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, 'test'); - // Change input encoding setting to bin - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const binEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-4'); - await userEvent.click(binEncodingMenuItem); - // Change output encoding setting to base64url - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64urlEncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-2'); - await userEvent.click(base64urlEncodingMenuItem); - - // Click RESUME_AUTO_PLAY button - const startAutoplayButton = await screen.findByTestId('start-autoplay-button'); - await userEvent.click(startAutoplayButton); - // Verify transition to state: validateInputText-error after event START_AUTOPLAY - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: 0101 - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '0101'); - // Change input encoding setting to bin - await userEvent.click(stringEncodingMenu); - await userEvent.click(binEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: validateInputText-error after event SKIP_DEMO - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="error"]'); - expect(domReflectsCurrentState).toBeTruthy(); - // Wait for state machine to transition back to 'inactive' state - await new Promise((r) => setTimeout(r, 1100)); - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - - // Set the value of the input data text box: 01110100011001010111001101110100 - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '01110100011001010111001101110100'); - // Change input encoding setting to bin - await userEvent.click(stringEncodingMenu); - await userEvent.click(binEncodingMenuItem); - // Change output encoding setting to base64url - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64urlEncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const utf8HappyPath: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: 🦦👨‍🌾🫥🏃🏿‍♀️☝🏾 - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '🦦👨‍🌾🫥🏃🏿‍♀️☝🏾'); - // Change input encoding setting to UTF-8 - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-2'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The first step in the Base64 encoding process is to convert the input data to binary`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-encodeByte after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="encodeByte"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `, which has binary value`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeInput"][data-sub-state="explainByteMapping"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `the input data has been converted to a sequence of 8-bit bytes.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createInputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createInputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The chunk size of 24-bits was chosen because it is divisible by 6`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createInputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createInputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` and final chunk (`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-regularIdle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="createOutputChunks"][data-sub-state="regularIdle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Next, for each chunk of input data with 24 bits (three 8-bit bytes)`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createOutputChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Since the final input chunk contains only `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-explainPadCharacter after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="explainPadCharacter"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: createOutputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector( - '[data-state="createOutputChunks"][data-sub-state="createLastPaddedChunk"]', - ); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = ` bits in this chunk are taken from `; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-idle after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="idle"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The final step is to convert each 6-bit value to the corresponding Base64 digit.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="encodeOutput"][data-sub-state="encodeBase64"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Base64 digit`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: verifyResults after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="verifyResults"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The input data has been successfully encoded as a string of Base64 characters!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: finished after event GO_TO_NEXT_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const utf8MixedAscii: JSDomTestFunction = async ( - screen: Screen, - userEvent: typeof UserEvent, - expect: Vi.ExpectStatic, -): Promise => { - // Set the value of the input data text box: ✓ à la mode - const inputTextBox = await screen.findByTestId('input-text'); - await userEvent.type(inputTextBox, '✓ à la mode'); - // Change input encoding setting to UTF-8 - const stringEncodingMenu = await screen.findByTestId('select-string-encoding-open-list-button'); - await userEvent.click(stringEncodingMenu); - const asciiEncodingMenuItem = await screen.findByTestId('select-string-encoding-option-2'); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - const base64EncodingMenu = await screen.findByTestId('select-base64-encoding-open-list-button'); - await userEvent.click(base64EncodingMenu); - const base64EncodingMenuItem = await screen.findByTestId('select-base64-encoding-option-1'); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await screen.findByTestId('next-step-button'); - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - let domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - const demoText = await screen.findByTestId('demo-text'); - let expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await screen.findByTestId('last-step-button'); - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_FIRST_STEP button - const firstStepButton = await screen.findByTestId('first-step-button'); - await userEvent.click(firstStepButton); - // Verify transition to state: inactive after event GO_TO_FIRST_STEP - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Enter a string value in the text box above to get started.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Set the value of the input data text box: ∑ßåœ ≈ ∆c - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '∑ßåœ ≈ ∆c'); - // Change input encoding setting to UTF-8 - await userEvent.click(stringEncodingMenu); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_FIRST_STEP button - await userEvent.click(firstStepButton); - // Verify transition to state: inactive after event GO_TO_FIRST_STEP - domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Enter a string value in the text box above to get started.`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Set the value of the input data text box: 日本語文字列 - await userEvent.clear(inputTextBox); - await userEvent.type(inputTextBox, '日本語文字列'); - // Change input encoding setting to UTF-8 - await userEvent.click(stringEncodingMenu); - await userEvent.click(asciiEncodingMenuItem); - // Change output encoding setting to base64 - await userEvent.click(base64EncodingMenu); - await userEvent.click(base64EncodingMenuItem); - - // Click GO_TO_NEXT_STEP button - await userEvent.click(nextStepButton); - // Verify transition to state: validateInputText-success after event VALIDATE_TEXT - domReflectsCurrentState = document.querySelector('[data-state="validateInputText"][data-sub-state="success"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `Nicely done! The value you provided looks, smells and tastes like a valid`; - expect(demoText.innerHTML).toContain(expectedTextForState); - - // Click GO_TO_LAST_STEP button - await userEvent.click(lastStepButton); - // Verify transition to state: finished after event GO_TO_LAST_STEP - domReflectsCurrentState = document.querySelector('[data-state="finished"][data-sub-state="none"]'); - expect(domReflectsCurrentState).toBeTruthy(); - expectedTextForState = `The encoding process is complete!`; - expect(demoText.innerHTML).toContain(expectedTextForState); -}; - -const fastTests: JSDomTestCase[] = [ - { description: 'encode ascii string, execute all steps manually', testFunction: asciiHappyPath }, - { description: 'encode ascii string, skip demo', testFunction: asciiHappyPathSkipDemo }, - { description: 'encode ascii string, validation error', testFunction: asciiValidationError }, - { description: 'encode ascii string, with symbol characters', testFunction: asciiWithSymbols }, - { description: 'encode hex string, execute all steps manually', testFunction: hexHappyPath }, - { description: 'encode hex string, validation error', testFunction: hexValidationError }, - { description: 'encode bin string, execute all steps manually', testFunction: binHappyPath }, - { description: 'encode bin string, skip demo', testFunction: binHappyPathSkipDemo }, - { description: 'encode bin string, validation error', testFunction: binValidationError }, - { description: 'encode utf8 string, execute all steps manually', testFunction: utf8HappyPath }, - { description: 'encode multiple utf8 strings, mix of ascii and utf8', testFunction: utf8MixedAscii }, -]; - -const slowTests: JSDomTestCase[] = [ - { description: 'encode ascii string, execute all steps with autoplay', testFunction: asciiHappyPathAutoplay }, -]; - -export const testPaths = import.meta.env.DEV ? fastTests : [...fastTests, ...slowTests]; -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPathsPuppeteer.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPathsPuppeteer.ts deleted file mode 100644 index 10e81dca..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testPathsPuppeteer.ts +++ /dev/null @@ -1,385 +0,0 @@ -/* c8 ignore start */ -import type { PuppeteerTestCase } from '$lib/xstate/b64Encode.test/types'; -import { machineStateDemoTextMap } from '$lib/xstate/b64Encode.test/util'; -import type { ElementHandle, Page } from 'puppeteer'; - -async function getInnerTextFromDomElements(results: ElementHandle[]): Promise { - const textContent = await Promise.all( - results.map(async (result) => { - const p = await result.getProperty('innerText'); - return p.toString().replace('JSHandle:', ''); - }), - ); - return textContent.join(' '); -} - -// const getInnerText = async (page: Page, elHandle: ElementHandle): Promise => await page.evaluate(el => el.innerText, elHandle); - -const asciiHappyPath = async (page: Page, expect: Vi.ExpectStatic): Promise => { - await page.goto('http://localhost:3500', { waitUntil: 'networkidle0' }); - - // Set the value of the input data text box: test - const inputTextBox = await page.waitForSelector(`[data-testid="input-text"]`); - await inputTextBox.type('test', { delay: 50 }); - await page.waitForTimeout(300); - // Change input encoding setting to ASCII - const stringEncodingMenu = await page.waitForSelector(`[data-testid="select-string-encoding-open-list-button"]`); - await stringEncodingMenu.click(); - const asciiEncodingMenuItem = await page.waitForSelector(`[data-testid="select-string-encoding-option-1"]`); - await asciiEncodingMenuItem.click(); - // Change output encoding setting to base64url - const base64EncodingMenu = await page.waitForSelector(`[data-testid="select-base64-encoding-open-list-button"]`); - await base64EncodingMenu.click(); - const base64urlEncodingMenuItem = await page.waitForSelector(`[data-testid="select-base64-encoding-option-2"]`); - await base64urlEncodingMenuItem.click(); - - // Click GO_TO_NEXT_STEP button - const nextStepButton = await page.waitForSelector(`[data-testid="next-step-button"]`); - await nextStepButton.click(); - // Verify machine state transitioned to validateInputText-success after event VALIDATE_TEXT - await page.waitForSelector('[data-state="validateInputText"]'); - await page.waitForSelector('[data-sub-state="success"]'); - // Verify UI contains correct text content for state: [object Object] - let results = await page.$x('//div[@data-state="validateInputText" and @data-sub-state="success"]//p'); - let demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('validateInputText-success')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-idle after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-state="encodeInput"]'); - await page.waitForSelector('[data-sub-state="idle"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="idle"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-idle')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-encodeByte after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeByte"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="encodeByte"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-encodeByte')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-encodeByte after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeByte"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="encodeByte"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-encodeByte')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-encodeByte after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeByte"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="encodeByte"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-encodeByte')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-encodeByte after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeByte"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="encodeByte"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-encodeByte')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeInput-explainByteMapping after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="explainByteMapping"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeInput" and @data-sub-state="explainByteMapping"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeInput-explainByteMapping')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createInputChunks-regularIdle after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-state="createInputChunks"]'); - await page.waitForSelector('[data-sub-state="regularIdle"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createInputChunks" and @data-sub-state="regularIdle"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createInputChunks-regularIdle')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createInputChunks-createInputChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="createInputChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createInputChunks" and @data-sub-state="createInputChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createInputChunks-createInputChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createInputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="explainLastPaddedChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createInputChunks" and @data-sub-state="explainLastPaddedChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createInputChunks-explainLastPaddedChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createInputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="createLastPaddedChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createInputChunks" and @data-sub-state="createLastPaddedChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createInputChunks-createLastPaddedChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createOutputChunks-regularIdle after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-state="createOutputChunks"]'); - await page.waitForSelector('[data-sub-state="regularIdle"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createOutputChunks" and @data-sub-state="regularIdle"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createOutputChunks-regularIdle')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createOutputChunks-createOutputChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="createOutputChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createOutputChunks" and @data-sub-state="createOutputChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createOutputChunks-createOutputChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createOutputChunks-explainLastPaddedChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="explainLastPaddedChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createOutputChunks" and @data-sub-state="explainLastPaddedChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createOutputChunks-explainLastPaddedChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createOutputChunks-explainPadCharacter after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="explainPadCharacter"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createOutputChunks" and @data-sub-state="explainPadCharacter"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createOutputChunks-explainPadCharacter')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to createOutputChunks-createLastPaddedChunk after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="createLastPaddedChunk"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="createOutputChunks" and @data-sub-state="createLastPaddedChunk"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('createOutputChunks-createLastPaddedChunk')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-idle after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-state="encodeOutput"]'); - await page.waitForSelector('[data-sub-state="idle"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="idle"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-idle')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to encodeOutput-encodeBase64 after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-sub-state="encodeBase64"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="encodeOutput" and @data-sub-state="encodeBase64"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('encodeOutput-encodeBase64')); - - // Click GO_TO_NEXT_STEP button - await nextStepButton.click(); - // Verify machine state transitioned to finished after event GO_TO_NEXT_STEP - await page.waitForSelector('[data-state="finished"]'); - await page.waitForSelector('[data-sub-state="none"]'); - // Verify UI contains correct text content for state: [object Object] - results = await page.$x('//div[@data-state="finished" and @data-sub-state="none"]//p'); - demoText = await getInnerTextFromDomElements(results); - expect(demoText).toContain(machineStateDemoTextMap.get('finished')); -}; - -const asciiHappyPathAutoplay = async (page: Page, expect: Vi.ExpectStatic): Promise => { - await page.goto('http://localhost:3500', { waitUntil: 'networkidle0' }); - - // Set the value of the input data text box: test - const inputTextBox = await page.waitForSelector(`[data-testid="input-text"]`); - await inputTextBox.type('test', { delay: 50 }); - await page.waitForTimeout(300); - // Change input encoding setting to ASCII - const stringEncodingMenu = await page.waitForSelector(`[data-testid="select-string-encoding-open-list-button"]`); - await stringEncodingMenu.click(); - const asciiEncodingMenuItem = await page.waitForSelector(`[data-testid="select-string-encoding-option-1"]`); - await asciiEncodingMenuItem.click(); - // Change output encoding setting to base64url - const base64EncodingMenu = await page.waitForSelector(`[data-testid="select-base64-encoding-open-list-button"]`); - await base64EncodingMenu.click(); - const base64urlEncodingMenuItem = await page.waitForSelector(`[data-testid="select-base64-encoding-option-2"]`); - await base64urlEncodingMenuItem.click(); - - // Click RESUME_AUTO_PLAY button - const startAutoplayButton = await page.waitForSelector(`[data-testid="start-autoplay-button"]`); - await startAutoplayButton.click(); - // Verify machine state transitioned to validateInputText-success after event START_AUTOPLAY - await page.waitForSelector('[data-state="validateInputText"]'); - await page.waitForSelector('[data-sub-state="success"]'); - - // Verify machine automatically transitions to next state: encodeInput-idle - await page.waitForSelector('[data-state="encodeInput"]'); - await page.waitForSelector('[data-sub-state="idle"]'); - - // Verify machine automatically transitions to next state: encodeInput-autoPlayEncodeByte - await page.waitForSelector('[data-sub-state="autoPlayEncodeByte"]'); - - // Verify machine automatically transitions to next state: encodeInput-explainByteMapping - await page.waitForSelector('[data-sub-state="explainByteMapping"]'); - - // Verify machine automatically transitions to next state: createInputChunks-autoPlayIdle - await page.waitForSelector('[data-state="createInputChunks"]'); - await page.waitForSelector('[data-sub-state="autoPlayIdle"]'); - - // Verify machine automatically transitions to next state: createInputChunks-autoPlayCreateInputChunk - await page.waitForSelector('[data-sub-state="autoPlayCreateInputChunk"]'); - - // Verify machine automatically transitions to next state: createInputChunks-explainLastPaddedChunk - await page.waitForSelector('[data-sub-state="explainLastPaddedChunk"]'); - - // Verify machine automatically transitions to next state: createInputChunks-createLastPaddedChunk - await page.waitForSelector('[data-sub-state="createLastPaddedChunk"]'); - - // Verify machine automatically transitions to next state: createOutputChunks-autoPlayIdle - await page.waitForSelector('[data-state="createOutputChunks"]'); - await page.waitForSelector('[data-sub-state="autoPlayIdle"]'); - - // Verify machine automatically transitions to next state: createOutputChunks-autoPlayCreateOutputChunk - await page.waitForSelector('[data-sub-state="autoPlayCreateOutputChunk"]'); - - // Verify machine automatically transitions to next state: createOutputChunks-explainLastPaddedChunk - await page.waitForSelector('[data-sub-state="explainLastPaddedChunk"]'); - - // Verify machine automatically transitions to next state: createOutputChunks-explainPadCharacter - await page.waitForSelector('[data-sub-state="explainPadCharacter"]'); - - // Verify machine automatically transitions to next state: createOutputChunks-createLastPaddedChunk - await page.waitForSelector('[data-sub-state="createLastPaddedChunk"]'); - - // Verify machine automatically transitions to next state: encodeOutput-idle - await page.waitForSelector('[data-state="encodeOutput"]'); - await page.waitForSelector('[data-sub-state="idle"]'); - - // Verify machine automatically transitions to next state: encodeOutput-autoPlayEncodeBase64 - await page.waitForSelector('[data-sub-state="autoPlayEncodeBase64"]'); - - // Verify machine automatically transitions to next state: finished - await page.waitForSelector('[data-state="finished"]'); - await page.waitForSelector('[data-sub-state="none"]'); -}; - -const asciiHappyPathSkipDemo = async (page: Page, expect: Vi.ExpectStatic): Promise => { - await page.goto('http://localhost:3500', { waitUntil: 'networkidle0' }); - - // Set the value of the input data text box: test - const inputTextBox = await page.waitForSelector(`[data-testid="input-text"]`); - await inputTextBox.type('test', { delay: 50 }); - // await page.waitForTimeout(300); - // Change input encoding setting to ASCII - const stringEncodingMenu = await page.waitForSelector(`[data-testid="select-string-encoding-open-list-button"]`); - await stringEncodingMenu.click(); - const asciiEncodingMenuItem = await page.waitForSelector(`[data-testid="select-string-encoding-option-1"]`); - await asciiEncodingMenuItem.click(); - // Change output encoding setting to base64url - const base64EncodingMenu = await page.waitForSelector(`[data-testid="select-base64-encoding-open-list-button"]`); - await base64EncodingMenu.click(); - const base64urlEncodingMenuItem = await page.waitForSelector(`[data-testid="select-base64-encoding-option-2"]`); - await base64urlEncodingMenuItem.click(); - - // Click GO_TO_LAST_STEP button - const lastStepButton = await page.waitForSelector(`[data-testid="last-step-button"]`); - await lastStepButton.click(); - // Verify machine state transitioned to finished after event SKIP_DEMO - await page.waitForSelector('[data-state="finished"]'); - await page.waitForSelector('[data-sub-state="none"]'); -}; - -export const testPathsPuppeteer: PuppeteerTestCase[] = [ - { description: 'encode ascii text, execute all steps manually', testFunction: asciiHappyPath }, - { description: 'encode ascii text, execute all steps with autoplay', testFunction: asciiHappyPathAutoplay }, - { description: 'encode ascii text, skip demo', testFunction: asciiHappyPathSkipDemo }, -]; -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGenerator.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGenerator.ts deleted file mode 100644 index 9f899a03..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGenerator.ts +++ /dev/null @@ -1,181 +0,0 @@ -/* c8 ignore start */ -import { isStringEncoding } from '$lib/typeguards'; -import type { Base64Encoding, StringEncoding } from '$lib/types'; -import { getRandomHexString } from '$lib/util'; -import type { - DataEvent, - MachineEvent, - MachineState, - MachineTestStepData, - SimpleEventType, -} from '$lib/xstate/b64Encode.test/types'; -import { - dataEventToSimpleEventMap, - encodingSettingElementIdMap, - formatStateName, - getElementHandleTracker, - getNavButtonTracker, - getScripObjectTracker, - isDataMachineEvent, - isSimpleMachineEvent, - machineStateDemoTextMap, - simpleEventTestDetailsMap, -} from '$lib/xstate/b64Encode.test/util'; - -const getAutoplayTimeout = (machineState: MachineState): number => - machineState.state === 'createInputChunks' && machineState.substate === 'createLastPaddedChunk' - ? 200 - : machineState.state === 'encodeOutput' && machineState.substate === 'encodeLastBase64' - ? 100 - : 1100; - -export function createTestScript( - testSteps: MachineTestStepData[], - scriptName: string, - ignoreUpdateTextEvents = true, -): string { - const instantiatedScriptObjects = getScripObjectTracker(); - const instantiatedNavButtons = getNavButtonTracker(); - const instantiatedHtmlElements = getElementHandleTracker(); - - function generateCodeForTestStep(testStep: MachineTestStepData): string { - const { event, expectedState } = testStep; - let testCode: string[] = []; - if (isSimpleMachineEvent(event)) { - testCode = generateCodeForSimpleEvent(event.type); - } - if (isDataMachineEvent(event)) { - testCode = generateCodeForDataEvent(event); - } - testCode = [...testCode, ...generateCodeForStateVerification(event, expectedState)]; - return testCode.join('\n'); - } - - function generateCodeForStateVerification(event: MachineEvent, machineState: MachineState): string[] { - const substate = machineState.substate === 'encodeLastBase64' ? 'autoPlayEncodeBase64' : machineState.substate; - const stateName = formatStateName(machineState); - const testCode: string[] = []; - if (event.type === 'BEGIN_DEMO') { - testCode.push(`// Verify initial state of machine is ${stateName}`); - } else if (event.type === 'AUTOPLAYING') { - const autoplayTimeout = getAutoplayTimeout(machineState); - testCode.push(`// Verify machine automatically transitions to next state: ${stateName}`); - testCode.push(`await new Promise((r) => setTimeout(r, ${autoplayTimeout}));`); - } else { - testCode.push(`// Verify transition to state: ${stateName} after event ${event.type}`); - } - - const queryExpectedMachineState = `let domReflectsCurrentState = document.querySelector('[data-state="${machineState.state}"][data-sub-state="${substate}"]');`; - const verifyExpectedMachineState = `expect(domReflectsCurrentState).toBeTruthy();`; - const instantiateDemoTextObject = `const demoText = await screen.findByTestId('demo-text');`; - const getExpectedDemoText = `let expectedTextForState = \`${machineStateDemoTextMap.get(stateName)}\`;`; - const verifyExpectedDemoText = `expect(demoText.innerHTML).toContain(expectedTextForState);`; - - if (!instantiatedScriptObjects.get('domReflectsCurrentState')) { - instantiatedScriptObjects.set('domReflectsCurrentState', true); - testCode.push(queryExpectedMachineState); - } else { - testCode.push(queryExpectedMachineState.slice(4)); - } - testCode.push(verifyExpectedMachineState); - if (machineState.state === 'validateInputText' && machineState.substate === 'error') { - testCode.push(`// Wait for state machine to transition back to 'inactive' state`); - testCode.push(`await new Promise((r) => setTimeout(r, 1100));`); - testCode.push( - `domReflectsCurrentState = document.querySelector('[data-state="inactive"][data-sub-state="none"]');`, - ); - testCode.push(`expect(domReflectsCurrentState).toBeTruthy();`); - } else { - if (!instantiatedScriptObjects.get('demoText')) { - instantiatedScriptObjects.set('demoText', true); - testCode.push(instantiateDemoTextObject); - testCode.push(getExpectedDemoText); - } else { - testCode.push(getExpectedDemoText.slice(4)); - } - testCode.push(verifyExpectedDemoText); - } - return testCode; - } - - function generateCodeForSimpleEvent(simpleEvent: SimpleEventType): string[] { - const testData = simpleEventTestDetailsMap.get(simpleEvent); - if (testData) { - const { variableName, id } = testData; - const testCode: string[] = []; - testCode.push(`// Click ${simpleEvent} button`); - if (!instantiatedNavButtons.get(simpleEvent)) { - testCode.push(`const ${variableName} = await screen.findByTestId('${id}');`); - instantiatedNavButtons.set(simpleEvent, true); - } - testCode.push(`await userEvent.click(${variableName});`); - return testCode; - } - } - - function generateCodeForDataEvent(dataEvent: DataEvent): string[] { - const { inputText, inputEncoding, outputEncoding } = dataEvent; - const changeFormSettingsCode = [ - ...getCodeToEditTextBox('input-text', inputText), - ...getCodeToChangeEncodingSetting(inputEncoding), - ...getCodeToChangeEncodingSetting(outputEncoding), - ]; - const simpleEvent = dataEventToSimpleEventMap.get(dataEvent.type); - if (!simpleEvent) { - return changeFormSettingsCode; - } - return [...changeFormSettingsCode, '\n\n', ...generateCodeForSimpleEvent(simpleEvent)]; - } - - function getCodeToEditTextBox(testId: string, input: string): string[] { - const testCode: string[] = []; - if (input) { - testCode.push(`// Set the value of the input data text box: ${input}`); - if (!instantiatedHtmlElements.get(testId)) { - instantiatedHtmlElements.set(testId, true); - testCode.push(`const inputTextBox = await screen.findByTestId('${testId}');`); - testCode.push(`await userEvent.type(inputTextBox, '${input}');`); - } else { - testCode.push(`await userEvent.clear(inputTextBox);`); - testCode.push(`await userEvent.type(inputTextBox, '${input}');`); - } - } - return testCode; - } - - function getCodeToChangeEncodingSetting(encoding: StringEncoding | Base64Encoding): string[] { - const inputType = isStringEncoding(encoding) ? 'input' : 'output'; - const encodingSettingMap = encodingSettingElementIdMap.get(encoding); - if (encodingSettingMap) { - const [menuId, menuItemId] = encodingSettingMap.ids; - const [menuName, menuItemName] = encodingSettingMap.variableNames; - const testCode: string[] = []; - testCode.push(`// Change ${inputType} encoding setting to ${encoding}`); - if (!instantiatedHtmlElements.get(menuId)) { - testCode.push(`const ${menuName} = await screen.findByTestId('${menuId}');`); - instantiatedHtmlElements.set(menuId, true); - } - testCode.push(`await userEvent.click(${menuName});`); - if (!instantiatedHtmlElements.get(menuItemId)) { - testCode.push(`const ${menuItemName} = await screen.findByTestId('${menuItemId}');`); - instantiatedHtmlElements.set(menuItemId, true); - } - testCode.push(`await userEvent.click(${menuItemName});`); - return testCode; - } - } - - if (scriptName === null) { - scriptName = `test${getRandomHexString(4)}`; - } - const functionDeclaration = `const ${scriptName}: JSDomTestFunction = async (screen: Screen, userEvent: UserEvent, expect: Vi.ExpectStatic): Promise => {`; - - const testScript = testSteps - .filter((step) => step) - .filter((step) => step.event.type !== 'UPDATE_TEXT' || !ignoreUpdateTextEvents) - .map(generateCodeForTestStep) - .join('\n\n'); - - return [functionDeclaration, testScript, '};'].join('\n'); -} -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGeneratorPuppeteer.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGeneratorPuppeteer.ts deleted file mode 100644 index 35f4dfe5..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testScriptGeneratorPuppeteer.ts +++ /dev/null @@ -1,176 +0,0 @@ -/* c8 ignore start */ -import { isStringEncoding } from '$lib/typeguards'; -import type { Base64Encoding, StringEncoding } from '$lib/types'; -import type { - DataEvent, - MachineEvent, - MachineState, - MachineTestStepData, - SimpleEventType, - TestEnvSettings, -} from '$lib/xstate/b64Encode.test/types'; -import { - dataEventToSimpleEventMap, - encodingSettingElementIdMap, - formatStateName, - getElementHandleTracker, - getNavButtonTracker, - isDataMachineEvent, - isNullMachineEvent, - isSimpleMachineEvent, - simpleEventTestDetailsMap, -} from '$lib/xstate/b64Encode.test/util'; - -export function createTestScript(testSteps: MachineTestStepData[], options?: TestEnvSettings): string { - let currentState: MachineState; - let instantiatedXPathObjects = false; - const instantiatedNavButtons = getNavButtonTracker(); - const instantiatedHtmlElements = getElementHandleTracker(); - const defaultOptions = { timeoutMs: 250, ignoreUpdateTextEvents: true, port: 3000 }; - const { timeoutMs, ignoreUpdateTextEvents, port } = { ...defaultOptions, ...options }; - - function generatePuppeteerCodeForStep(testStep: MachineTestStepData): string { - const { event, expectedState } = testStep; - if (isNullMachineEvent(event.type)) { - if (currentState?.state !== expectedState.state || currentState?.substate !== expectedState.substate) { - return generatePuppeteerCodeForStateVerification(event, expectedState); - } - } - if (isSimpleMachineEvent(event)) { - const testCode = [ - generatePuppeteerCodeForSimpleEvent(event.type), - generatePuppeteerCodeForStateVerification(event, expectedState), - ]; - return testCode.join('\n'); - } - if (isDataMachineEvent(event)) { - const testCode = [ - generatePuppeteerCodeForDataEvent(event), - generatePuppeteerCodeForStateVerification(event, expectedState), - ]; - return testCode.join('\n'); - } - } - - function generatePuppeteerCodeForStateVerification(event: MachineEvent, machineState: MachineState): string { - const { state, substate } = machineState; - const stateName = formatStateName(machineState); - const testCode = []; - if (event.type === 'BEGIN_DEMO') { - testCode.push(`// Verify initial state of machine is ${stateName}`); - } else if (event.type === 'AUTOPLAYING') { - testCode.push(`// Verify machine automatically transitions to next state: ${stateName}`); - } else { - testCode.push(`// Verify machine state transitioned to ${stateName} after event ${event.type}`); - } - if (currentState?.state !== state) { - testCode.push(`await page.waitForSelector('[data-state="${state}"]');`); - } - currentState = machineState; - testCode.push(`await page.waitForSelector('[data-sub-state="${substate}"]');`); - testCode.push(generatePuppeteerCodeToVerifyDemoText()); - return testCode.join('\n'); - } - - function generatePuppeteerCodeToVerifyDemoText(): string { - const { state, substate } = currentState; - const stateName = formatStateName(currentState); - let objectAssignments = [ - `let results = await page.$x('//div[@data-state="${state}" and @data-sub-state="${substate}"]//p');`, - `let demoText = await getInnerTextFromDomElements(results);`, - ]; - if (!instantiatedXPathObjects) { - instantiatedXPathObjects = true; - } else { - objectAssignments = objectAssignments.map((s) => s.slice(4)); - } - const testCode = [ - `// Verify UI contains correct text content for state: ${stateName}`, - ...objectAssignments, - `expect(demoText).toContain(machineStateDemoTextMap.get("${stateName}"));`, - ]; - return testCode.join('\n'); - } - - function generatePuppeteerCodeForSimpleEvent(simpleEvent: SimpleEventType): string { - const testData = simpleEventTestDetailsMap.get(simpleEvent); - if (testData) { - const { variableName, id } = testData; - const testCode = []; - testCode.push(`// Click ${simpleEvent} button`); - if (!instantiatedNavButtons.get(simpleEvent)) { - testCode.push(`const ${variableName} = await page.waitForSelector(\`[data-testid="${id}"]\`);`); - testCode.push(`await ${variableName}.click();`); - instantiatedNavButtons.set(simpleEvent, true); - } else { - testCode.push(`await ${variableName}.click();`); - } - return testCode.join('\n'); - } - } - - function generatePuppeteerCodeForDataEvent(dataEvent: DataEvent): string { - const { inputText, inputEncoding, outputEncoding } = dataEvent; - const changeFormSettingsCode = [ - getPuppeteerCodeToEditTextBox('input-text', inputText), - getPuppeteerCodeToChangeEncodingSetting(inputEncoding), - getPuppeteerCodeToChangeEncodingSetting(outputEncoding), - ]; - const simpleEvent = dataEventToSimpleEventMap.get(dataEvent.type); - if (!simpleEvent) { - return changeFormSettingsCode.join('\n'); - } - const testCode = [changeFormSettingsCode.join('\n'), generatePuppeteerCodeForSimpleEvent(simpleEvent)]; - return testCode.join('\n\n'); - } - - function getPuppeteerCodeToChangeEncodingSetting(encoding: StringEncoding | Base64Encoding): string { - const inputType = isStringEncoding(encoding) ? 'input' : 'output'; - const encodingSettingMap = encodingSettingElementIdMap.get(encoding); - if (encodingSettingMap) { - const [menuId, menuItemId] = encodingSettingMap.ids; - const [menuName, menuItemName] = encodingSettingMap.variableNames; - const testCode = []; - testCode.push(`// Change ${inputType} encoding setting to ${encoding}`); - if (!instantiatedHtmlElements.get(menuId)) { - testCode.push(`const ${menuName} = await page.waitForSelector(\`[data-testid="${menuId}"]\`);`); - testCode.push(`await ${menuName}.click();`); - instantiatedHtmlElements.set(menuId, true); - } else { - testCode.push(`await ${menuName}.click();`); - } - if (!instantiatedHtmlElements.get(menuItemId)) { - testCode.push(`const ${menuItemName} = await page.waitForSelector(\`[data-testid="${menuItemId}"]\`);`); - testCode.push(`await ${menuItemName}.click();`); - instantiatedHtmlElements.set(menuItemId, true); - } else { - testCode.push(`await ${menuItemName}.click();`); - } - return testCode.join('\n'); - } - } - - function getPuppeteerCodeToEditTextBox(testId: string, input: string) { - const testCode = []; - testCode.push(`// Set the value of the input data text box: ${input}`); - if (!instantiatedHtmlElements.get(testId)) { - testCode.push(`const inputTextBox = await page.waitForSelector(\`[data-testid="${testId}"]\`);`); - testCode.push(`await inputTextBox.type('${input}', { delay: 50 });`); - instantiatedHtmlElements.set(testId, true); - } else { - testCode.push(`await inputTextBox.type('${input}', { delay: 50 });`); - } - testCode.push(`await page.waitForTimeout(${timeoutMs});`); - return testCode.join('\n'); - } - - const codeSteps = testSteps.map((step) => { - const ignoreStep = ignoreUpdateTextEvents && step.event.type === 'UPDATE_TEXT'; - if (!ignoreStep) { - return generatePuppeteerCodeForStep(step); - } - }); - - return [`await page.goto('http://localhost:${port}', {waitUntil: 'networkidle0'})`, ...codeSteps].join('\n\n'); -} -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testSetGenerator.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/testSetGenerator.ts deleted file mode 100644 index f0c0077b..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/testSetGenerator.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* c8 ignore start */ -import { testScriptEvents } from '$lib/xstate/b64Encode.test/testEvents'; -import { createTestScript } from '$lib/xstate/b64Encode.test/testScriptGenerator'; -import type { TestFunctionInputData } from '$lib/xstate/b64Encode.test/types'; - -const generateJSDomTestCaseCode = (test: TestFunctionInputData): string => - `{ description: '${test.description}', testFunction: ${test.scriptName} },`; - -export function createTestSet() { - const imports = `/* c8 ignore start */ - import type { JSDomTestCase, JSDomTestFunction } from '$lib/xstate/b64Encode.test/types'; - import type { Screen } from '@testing-library/svelte'; - import type { UserEvent } from '@testing-library/user-event/dist/types/setup';`; - - const testFunctions = testScriptEvents.map(({ scriptName, events }) => createTestScript(events, scriptName, true)); - const fastTests = testScriptEvents.filter((test) => test.type === 'fast').map(generateJSDomTestCaseCode); - const slowTests = testScriptEvents.filter((test) => test.type === 'slow').map(generateJSDomTestCaseCode); - - const fastExportDeclarations = [`const fastTests: JSDomTestCase[] = [`, ...fastTests, `];`].join('\n'); - const slowExportDeclarations = [`const slowTests: JSDomTestCase[] = [`, ...slowTests, `];`].join('\n'); - const finalExports = [ - `export const testPaths = import.meta.env.DEV ? fastTests : [...fastTests, ...slowTests];`, - `/* c8 ignore stop */`, - ].join('\n'); - - const exports = [fastExportDeclarations, slowExportDeclarations, finalExports]; - - return [imports, ...testFunctions, ...exports].join('\n\n'); -} -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/types.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/types.ts deleted file mode 100644 index eacd9676..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/types.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* c8 ignore start */ -import type { Base64Encoding, StringEncoding } from '$lib/types'; -import type { DATA_EVENT_TYPES, NULL_EVENT_TYPES, SIMPLE_EVENT_TYPES } from '$lib/xstate/b64Encode.test/util'; -import type { Matcher, MatcherOptions, Screen, waitForOptions } from '@testing-library/svelte'; -import type { UserEvent } from '@testing-library/user-event/dist/types/setup'; -import type { Page } from 'puppeteer'; -import type { Writable } from 'svelte/store'; - -export type NullEventType = typeof NULL_EVENT_TYPES[number]; -export type SimpleEventType = typeof SIMPLE_EVENT_TYPES[number]; -export type DataEventType = typeof DATA_EVENT_TYPES[number]; -export type MachineEventType = NullEventType | SimpleEventType | DataEventType; - -export type NullEvent = { type: NullEventType }; -export type SimpleEvent = { type: SimpleEventType }; - -export type DataEvent = { - type: DataEventType; - inputText: string; - inputEncoding: StringEncoding; - outputEncoding: Base64Encoding; -}; - -export type MachineEvent = NullEvent | SimpleEvent | DataEvent; -export type MachineState = { state: string; substate: string }; -export type MachineLogs = { events: MachineEvent[]; states: MachineState[] }; -export type MachineLogItem = MachineEvent | MachineState; - -export type MachineTestStepData = { - event: MachineEvent; - expectedState: MachineState; -}; - -export interface EventLogStore { - subscribe: Writable['subscribe']; - update: Writable['update']; - add: (event: MachineEvent) => void; - entries: () => MachineTestStepData[]; - testScript: (scriptName?: string, ignoreUpdateTextEvents?: boolean) => string; - clear: () => void; -} - -export type SimpleEventTestDetails = { buttonName: string; testId: string }; -export type SimpleEventTestDetailsMap = { type: SimpleEventType; data: SimpleEventTestDetails }; -export type DataEventToSimpleEventMap = { dataEvent: DataEventType; simpleEvent: SimpleEventType }; - -export type HtmlElementIdMap = { id: string; variableName: string }; -export type HtmlElementIds = { ids: [string, string]; variableNames: [string, string] }; -export type TestEnvSettings = { timeoutMs?: number; ignoreUpdateTextEvents?: boolean; port?: number }; - -export type DomQueryByTestId = ( - id: Matcher, - options?: MatcherOptions, - waitForElementOptions?: waitForOptions, -) => Promise; - -export type PuppeteerTestFunction = (page: Page, expect: Vi.ExpectStatic) => Promise; -export type PuppeteerTestCase = { description: string; testFunction: PuppeteerTestFunction }; - -export type JSDomTestFunction = (screen: Screen, userEvent: UserEvent, expect: Vi.ExpectStatic) => Promise; -export type JSDomTestCase = { description: string; testFunction: JSDomTestFunction }; - -export type TestFunctionInputData = { - scriptName: string; - description: string; - type: 'fast' | 'slow'; - events: MachineTestStepData[]; -}; -/* c8 ignore stop */ diff --git a/apps/svelte-base64/src/lib/xstate/b64Encode.test/util.ts b/apps/svelte-base64/src/lib/xstate/b64Encode.test/util.ts deleted file mode 100644 index 3e8ec00d..00000000 --- a/apps/svelte-base64/src/lib/xstate/b64Encode.test/util.ts +++ /dev/null @@ -1,252 +0,0 @@ -/* c8 ignore start */ -import type { Base64Encoding, StringEncoding } from '$lib/types'; -import type { - DataEvent, - DataEventType, - HtmlElementIdMap, - HtmlElementIds, - MachineEvent, - MachineEventType, - MachineLogs, - MachineState, - MachineTestStepData, - NullEventType, - SimpleEvent, - SimpleEventType, -} from '$lib/xstate/b64Encode.test/types'; - -export function reconcileEventAndStateLists(events: MachineEvent[], states: MachineState[]): MachineLogs { - if (events.length === states.length) { - ({ events, states } = removeRedundantAutoPlayEntries(events, states)); - ({ events, states } = identifyEncodeOutputByteFinalStep(events, states)); - } - return { events, states }; -} - -function removeRedundantAutoPlayEntries(events: MachineEvent[], states: MachineState[]): MachineLogs { - const redundentIndices: number[] = []; - events.forEach((event, i) => { - if (event.type === 'START_AUTOPLAY' && i < events.length - 1) { - if (events[i + 1].type === 'AUTOPLAYING') { - redundentIndices.push(i + 1); - } - } - }); - if (redundentIndices.length) { - let reconciledEvents: MachineEvent[] = []; - let reconciledStates: MachineState[] = []; - for (const i of redundentIndices.reverse()) { - reconciledEvents = [...events.slice(0, i), ...events.slice(i + 1)]; - reconciledStates = [...states.slice(0, i), ...states.slice(i + 1)]; - } - return { events: reconciledEvents, states: reconciledStates }; - } - return { events, states }; -} - -function identifyEncodeOutputByteFinalStep(events: MachineEvent[], states: MachineState[]): MachineLogs { - if (states.length >= 2) { - const [penultimate, final] = states.slice(-2); - if ( - final.state === 'finished' && - penultimate.state === 'encodeOutput' && - penultimate.substate === 'autoPlayEncodeBase64' - ) { - penultimate.substate = 'encodeLastBase64'; - } - } - return { events, states }; -} - -export function createMachineTestStepData(events: MachineEvent[], states: MachineState[]): MachineTestStepData[] { - if (events.length === states.length) { - return Array.from({ length: events.length }, (_, i) => ({ event: events[i], expectedState: states[i] })); - } -} - -export const NULL_EVENT_TYPES = ['BEGIN_DEMO', 'AUTOPLAYING'] as const; - -export const SIMPLE_EVENT_TYPES = [ - 'RESET', - 'GO_TO_FIRST_STEP', - 'GO_TO_PREV_STEP', - 'GO_TO_NEXT_STEP', - 'GO_TO_LAST_STEP', - 'RESUME_AUTO_PLAY', - 'STOP_AUTO_PLAY', -] as const; - -export const DATA_EVENT_TYPES = ['UPDATE_TEXT', 'VALIDATE_TEXT', 'START_AUTOPLAY', 'SKIP_DEMO'] as const; - -function getSimpleEventTestDetailsMap(): Map { - const simpleEventTestDetailsMap = new Map(); - simpleEventTestDetailsMap.set('RESET', { variableName: 'resetButton', id: 'reset-button' }); - simpleEventTestDetailsMap.set('GO_TO_FIRST_STEP', { variableName: 'firstStepButton', id: 'first-step-button' }); - simpleEventTestDetailsMap.set('GO_TO_PREV_STEP', { variableName: 'prevStepButton', id: 'previous-step-button' }); - simpleEventTestDetailsMap.set('GO_TO_NEXT_STEP', { variableName: 'nextStepButton', id: 'next-step-button' }); - simpleEventTestDetailsMap.set('GO_TO_LAST_STEP', { variableName: 'lastStepButton', id: 'last-step-button' }); - simpleEventTestDetailsMap.set('RESUME_AUTO_PLAY', { - variableName: 'startAutoplayButton', - id: 'start-autoplay-button', - }); - simpleEventTestDetailsMap.set('STOP_AUTO_PLAY', { variableName: 'stopAutoplayButton', id: 'stop-autoplay-button' }); - return simpleEventTestDetailsMap; -} - -export const simpleEventTestDetailsMap = getSimpleEventTestDetailsMap(); - -function getDataEventToSimpleEventMap(): Map { - const dataEventToSimpleEventMap = new Map(); - dataEventToSimpleEventMap.set('UPDATE_TEXT', null); - dataEventToSimpleEventMap.set('VALIDATE_TEXT', 'GO_TO_NEXT_STEP'); - dataEventToSimpleEventMap.set('START_AUTOPLAY', 'RESUME_AUTO_PLAY'); - dataEventToSimpleEventMap.set('SKIP_DEMO', 'GO_TO_LAST_STEP'); - return dataEventToSimpleEventMap; -} - -export const dataEventToSimpleEventMap = getDataEventToSimpleEventMap(); - -function getEncodingSettingElementIdMap(): Map { - const encodingSettingElementIdMap = new Map(); - encodingSettingElementIdMap.set('ascii', { - ids: ['select-string-encoding-open-list-button', 'select-string-encoding-option-1'], - variableNames: ['stringEncodingMenu', 'asciiEncodingMenuItem'], - }); - encodingSettingElementIdMap.set('utf8', { - ids: ['select-string-encoding-open-list-button', 'select-string-encoding-option-2'], - variableNames: ['stringEncodingMenu', 'asciiEncodingMenuItem'], - }); - encodingSettingElementIdMap.set('hex', { - ids: ['select-string-encoding-open-list-button', 'select-string-encoding-option-3'], - variableNames: ['stringEncodingMenu', 'hexEncodingMenuItem'], - }); - encodingSettingElementIdMap.set('bin', { - ids: ['select-string-encoding-open-list-button', 'select-string-encoding-option-4'], - variableNames: ['stringEncodingMenu', 'binEncodingMenuItem'], - }); - encodingSettingElementIdMap.set('base64', { - ids: ['select-base64-encoding-open-list-button', 'select-base64-encoding-option-1'], - variableNames: ['base64EncodingMenu', 'base64EncodingMenuItem'], - }); - encodingSettingElementIdMap.set('base64url', { - ids: ['select-base64-encoding-open-list-button', 'select-base64-encoding-option-2'], - variableNames: ['base64EncodingMenu', 'base64urlEncodingMenuItem'], - }); - return encodingSettingElementIdMap; -} - -export const encodingSettingElementIdMap = getEncodingSettingElementIdMap(); - -function getMachineStateDemoTextMap(): Map { - const machineStateDemoTextMap = new Map(); - machineStateDemoTextMap.set('inactive', 'Enter a string value in the text box above to get started.'); - machineStateDemoTextMap.set('validateInputText-error', 'Enter a string value in the text box above to get started.'); - machineStateDemoTextMap.set( - 'validateInputText-success', - 'Nicely done! The value you provided looks, smells and tastes like a valid', - ); - machineStateDemoTextMap.set( - 'encodeInput-idle', - 'The first step in the Base64 encoding process is to convert the input data to binary', - ); - machineStateDemoTextMap.set('encodeInput-encodeByte', ', which has binary value'); - machineStateDemoTextMap.set('encodeInput-autoPlayEncodeByte', ', which has binary value'); - machineStateDemoTextMap.set( - 'encodeInput-explainByteMapping', - 'the input data has been converted to a sequence of 8-bit bytes.', - ); - machineStateDemoTextMap.set( - 'createInputChunks-regularIdle', - 'Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).', - ); - machineStateDemoTextMap.set( - 'createInputChunks-autoPlayIdle', - 'Three 8-bit bytes of input data (3x8 = 24 bits) can be represented by four 6-bit Base64 digits (4x6 = 24 bits).', - ); - machineStateDemoTextMap.set('createInputChunks-createInputChunk', ' chunk ('); - machineStateDemoTextMap.set('createInputChunks-autoPlayCreateInputChunk', ' chunk ('); - machineStateDemoTextMap.set( - 'createInputChunks-explainLastPaddedChunk', - 'The chunk size of 24-bits was chosen because it is divisible by 6', - ); - machineStateDemoTextMap.set('createInputChunks-createLastPaddedChunk', ' and final chunk ('); - machineStateDemoTextMap.set( - 'createOutputChunks-regularIdle', - 'Next, for each chunk of input data with 24 bits (three 8-bit bytes)', - ); - machineStateDemoTextMap.set( - 'createOutputChunks-autoPlayIdle', - 'Next, for each chunk of input data with three 8-bit bytes', - ); - machineStateDemoTextMap.set('createOutputChunks-createOutputChunk', ' bits in this chunk are taken from '); - machineStateDemoTextMap.set('createOutputChunks-autoPlayCreateOutputChunk', ' bits in this chunk are taken from '); - machineStateDemoTextMap.set( - 'createOutputChunks-explainLastPaddedChunk', - 'Since the final input chunk contains only ', - ); - machineStateDemoTextMap.set( - 'createOutputChunks-explainPadCharacter', - 'For various reasons, it is considered best practice to always structure Base64 data in groups of four digits.', - ); - machineStateDemoTextMap.set('createOutputChunks-createLastPaddedChunk', ' bits in this chunk are taken from '); - machineStateDemoTextMap.set( - 'encodeOutput-idle', - 'The final step is to convert each 6-bit value to the corresponding Base64 digit.', - ); - machineStateDemoTextMap.set('encodeOutput-encodeBase64', 'Base64 digit'); - machineStateDemoTextMap.set('encodeOutput-autoPlayEncodeBase64', 'Base64 digit'); - machineStateDemoTextMap.set('encodeOutput-encodeLastBase64', 'Base64 digit'); - machineStateDemoTextMap.set( - 'verifyResults', - 'The input data has been successfully encoded as a string of Base64 characters!', - ); - machineStateDemoTextMap.set('finished', 'The encoding process is complete!'); - return machineStateDemoTextMap; -} - -export const machineStateDemoTextMap = getMachineStateDemoTextMap(); - -export function getNavButtonTracker(): Map { - const navButtonMap = new Map(); - navButtonMap.set('RESET', false); - navButtonMap.set('GO_TO_FIRST_STEP', false); - navButtonMap.set('GO_TO_PREV_STEP', false); - navButtonMap.set('GO_TO_NEXT_STEP', false); - navButtonMap.set('GO_TO_LAST_STEP', false); - navButtonMap.set('RESUME_AUTO_PLAY', false); - navButtonMap.set('STOP_AUTO_PLAY', false); - return navButtonMap; -} - -export function getElementHandleTracker(): Map { - const elementMap = new Map(); - elementMap.set('input-text', false); - elementMap.set('select-string-encoding-open-list-button', false); - elementMap.set('select-base64-encoding-open-list-button', false); - elementMap.set('select-string-encoding-option-1', false); - elementMap.set('select-string-encoding-option-3', false); - elementMap.set('select-string-encoding-option-4', false); - elementMap.set('select-base64-encoding-option-1', false); - elementMap.set('select-base64-encoding-option-2', false); - return elementMap; -} - -export function getScripObjectTracker(): Map { - const objectMap = new Map(); - objectMap.set('domReflectsCurrentState', false); - objectMap.set('expectedTextForState', false); - return objectMap; -} - -export const isNullMachineEvent = (event: MachineEventType): event is NullEventType => - NULL_EVENT_TYPES.some((type) => event === type); - -export const isSimpleMachineEvent = (event: MachineEvent): event is SimpleEvent => - SIMPLE_EVENT_TYPES.some((type) => event.type === type); - -export const isDataMachineEvent = (event: MachineEvent): event is DataEvent => - DATA_EVENT_TYPES.some((type) => event.type === type); - -export const formatStateName = (state: MachineState): string => - `${state.state}${state.substate !== 'none' ? `-${state.substate}` : ``}`; -/* c8 ignore stop */ diff --git a/apps/svelte-base64/tests/algoDemoTester.ts b/apps/svelte-base64/tests/algorithmDemoPage.ts similarity index 99% rename from apps/svelte-base64/tests/algoDemoTester.ts rename to apps/svelte-base64/tests/algorithmDemoPage.ts index fffbf67f..856992fd 100644 --- a/apps/svelte-base64/tests/algoDemoTester.ts +++ b/apps/svelte-base64/tests/algorithmDemoPage.ts @@ -2,7 +2,7 @@ import { expect, type Locator, type Page } from '@playwright/test'; export type MachineState = { state: string; substate: string }; -export class AlgoDemoTester { +export class AlgorithmDemoPage { readonly page: Page; readonly inputTextBox: Locator; readonly stringEncodingMenu: Locator; diff --git a/apps/svelte-base64/tests/base64.test.ts b/apps/svelte-base64/tests/base64.test.ts index 9344c19c..0cbc6cbd 100644 --- a/apps/svelte-base64/tests/base64.test.ts +++ b/apps/svelte-base64/tests/base64.test.ts @@ -47,7 +47,7 @@ describe('Base64Encoder', () => { expect(chunk5HexByte2Map?.bin_word2).toBe('0100'); const chunk5Base64Digit4Map = chunk5?.base64Map[3]; expect(chunk5Base64Digit4Map?.b64).toBe('='); - expect(chunk5Base64Digit4Map?.dec).toBe(null); + expect(chunk5Base64Digit4Map?.dec).toBe(0); expect(chunk5Base64Digit4Map?.bin).toBe(''); }); }); diff --git a/apps/svelte-base64/tests/dataPrep.test.ts b/apps/svelte-base64/tests/dataPrep.test.ts index 9f9a1dc7..3953c1f2 100644 --- a/apps/svelte-base64/tests/dataPrep.test.ts +++ b/apps/svelte-base64/tests/dataPrep.test.ts @@ -12,8 +12,8 @@ describe('validateEncoderInputChunks', () => { value: 'dog', }, bytes: [100, 111, 103], - hex: '64 6F 67', hexBytes: ['64', '6F', '67'], + hex: '64 6F 67', ascii: 'dog', utf8: { utf8: 'dog', @@ -23,6 +23,7 @@ describe('validateEncoderInputChunks', () => { encoded: 'dog', totalBytes: 3, hexBytes: ['64', '6F', '67'], + hexMap: [], bytes: [100, 111, 103], charMap: [ { @@ -31,7 +32,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['64'], bytes: [100], - codepoints: ['U+64'], + codepoints: ['U+0064'], totalBytes: 1, encoded: 'd', }, @@ -41,7 +42,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['6F'], bytes: [111], - codepoints: ['U+6F'], + codepoints: ['U+006F'], totalBytes: 1, encoded: 'o', }, @@ -51,7 +52,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['67'], bytes: [103], - codepoints: ['U+67'], + codepoints: ['U+0067'], totalBytes: 1, encoded: 'g', }, @@ -79,7 +80,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: '4', ascii: 'd', + char: 'd', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 111, @@ -88,7 +93,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: 'F', ascii: 'o', + char: 'o', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 103, @@ -97,7 +106,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: '7', ascii: 'g', + char: 'g', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, ], }, @@ -115,8 +128,8 @@ describe('validateEncoderInputChunks', () => { value: 'do', }, bytes: [100, 111], - hex: '64 6F', hexBytes: ['64', '6F'], + hex: '64 6F', ascii: 'do', utf8: { utf8: 'do', @@ -126,6 +139,7 @@ describe('validateEncoderInputChunks', () => { encoded: 'do', totalBytes: 2, hexBytes: ['64', '6F'], + hexMap: [], bytes: [100, 111], charMap: [ { @@ -134,7 +148,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['64'], bytes: [100], - codepoints: ['U+64'], + codepoints: ['U+0064'], totalBytes: 1, encoded: 'd', }, @@ -144,7 +158,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['6F'], bytes: [111], - codepoints: ['U+6F'], + codepoints: ['U+006F'], totalBytes: 1, encoded: 'o', }, @@ -172,7 +186,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: '4', ascii: 'd', + char: 'd', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 111, @@ -181,7 +199,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: 'F', ascii: 'o', + char: 'o', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, ], }, @@ -199,8 +221,8 @@ describe('validateEncoderInputChunks', () => { value: ' do', }, bytes: [32, 100, 111], - hex: '20 64 6F', hexBytes: ['20', '64', '6F'], + hex: '20 64 6F', ascii: ' do', utf8: { utf8: ' do', @@ -210,6 +232,7 @@ describe('validateEncoderInputChunks', () => { encoded: '%20do', totalBytes: 3, hexBytes: ['20', '64', '6F'], + hexMap: [], bytes: [32, 100, 111], charMap: [ { @@ -218,7 +241,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['20'], bytes: [32], - codepoints: ['U+20'], + codepoints: ['U+0020'], totalBytes: 1, encoded: '%20', }, @@ -228,7 +251,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['64'], bytes: [100], - codepoints: ['U+64'], + codepoints: ['U+0064'], totalBytes: 1, encoded: 'd', }, @@ -238,7 +261,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['6F'], bytes: [111], - codepoints: ['U+6F'], + codepoints: ['U+006F'], totalBytes: 1, encoded: 'o', }, @@ -266,7 +289,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '2', hex_word2: '0', ascii: 'ws', + char: ' ', isWhiteSpace: true, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 100, @@ -275,7 +302,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: '4', ascii: 'd', + char: 'd', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 111, @@ -284,7 +315,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: 'F', ascii: 'o', + char: 'o', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, ], }, @@ -302,8 +337,8 @@ describe('validateEncoderInputChunks', () => { value: ' d', }, bytes: [32, 100], - hex: '20 64', hexBytes: ['20', '64'], + hex: '20 64', ascii: ' d', utf8: { utf8: ' d', @@ -313,6 +348,7 @@ describe('validateEncoderInputChunks', () => { encoded: '%20d', totalBytes: 2, hexBytes: ['20', '64'], + hexMap: [], bytes: [32, 100], charMap: [ { @@ -321,7 +357,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['20'], bytes: [32], - codepoints: ['U+20'], + codepoints: ['U+0020'], totalBytes: 1, encoded: '%20', }, @@ -331,7 +367,7 @@ describe('validateEncoderInputChunks', () => { isASCII: true, hexBytes: ['64'], bytes: [100], - codepoints: ['U+64'], + codepoints: ['U+0064'], totalBytes: 1, encoded: 'd', }, @@ -359,7 +395,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '2', hex_word2: '0', ascii: 'ws', + char: ' ', isWhiteSpace: true, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 100, @@ -368,7 +408,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '6', hex_word2: '4', ascii: 'd', + char: 'd', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, ], }, @@ -386,10 +430,107 @@ describe('validateEncoderInputChunks', () => { value: '5f3c0a', }, bytes: [95, 60, 10], - hex: '5F 3C 0A', hexBytes: ['5F', '3C', '0A'], + hex: '5F 3C 0A', ascii: '', - utf8: null, + utf8: { + utf8: '', + hasCharacterNames: false, + hasCombinedChars: false, + stringLength: 0, + encoded: '', + totalBytes: 0, + hexBytes: [], + hexMap: [ + { + byte: 0, + bin_word1: '', + bin_word2: '', + hex_word1: '', + hex_word2: '', + ascii: '', + char: '', + isWhiteSpace: false, + groupId: '', + bitGroups: [ + { + groupId: '', + bits: '', + }, + ], + characterId: '', + }, + ], + bytes: [], + charMap: [ + { + char: '', + isCombined: false, + isASCII: false, + hexBytes: [], + bytes: [], + codepoints: [], + unicodeNames: [], + unicodeBlocks: [], + totalBytes: 0, + encoded: '', + charMap: [ + { + char: '', + isCombined: false, + isASCII: false, + hexBytes: [], + bytes: [], + codepoint: '', + unicodeName: '', + unicodeBlock: '', + totalBytes: 0, + encoded: '', + hexMap: [ + { + byte: 0, + bin_word1: '', + bin_word2: '', + hex_word1: '', + hex_word2: '', + ascii: '', + char: '', + isWhiteSpace: false, + groupId: '', + bitGroups: [ + { + groupId: '', + bits: '', + }, + ], + characterId: '', + }, + ], + }, + ], + hexMap: [ + { + byte: 0, + bin_word1: '', + bin_word2: '', + hex_word1: '', + hex_word2: '', + ascii: '', + char: '', + isWhiteSpace: false, + groupId: '', + bitGroups: [ + { + groupId: '', + bits: '', + }, + ], + characterId: '', + }, + ], + }, + ], + }, binary: '010111110011110000001010', totalChunks: 1, lastChunkPadded: false, @@ -412,7 +553,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '5', hex_word2: 'F', ascii: '', + char: '_', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 60, @@ -421,7 +566,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '3', hex_word2: 'C', ascii: '', + char: '<', isWhiteSpace: false, + groupId: '', + bitGroups: [], + characterId: '', }, { byte: 10, @@ -430,7 +579,11 @@ describe('validateEncoderInputChunks', () => { hex_word1: '0', hex_word2: 'A', ascii: '', - isWhiteSpace: false, + char: '\n', + isWhiteSpace: true, + groupId: '', + bitGroups: [], + characterId: '', }, ], }, @@ -448,10 +601,10 @@ describe('validateDecoderInputChunks', () => { success: true, }, base64: 'ZG9n', + binary: '011001000110111101100111', totalChunks: 1, lastChunkPadded: false, padLength: 0, - binary: '011001000110111101100111', chunks: [ { base64: 'ZG9n', @@ -465,24 +618,32 @@ describe('validateDecoderInputChunks', () => { dec: 25, b64: 'Z', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '000110', dec: 6, b64: 'G', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '111101', dec: 61, b64: '9', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '100111', dec: 39, b64: 'n', isPad: false, + groupId: '', + bitGroups: [], }, ], }, @@ -498,10 +659,10 @@ describe('validateDecoderInputChunks', () => { success: true, }, base64: 'ZG8', + binary: '011001000110111100', totalChunks: 1, lastChunkPadded: true, padLength: 1, - binary: '011001000110111100', chunks: [ { base64: 'ZG8', @@ -515,24 +676,32 @@ describe('validateDecoderInputChunks', () => { dec: 25, b64: 'Z', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '000110', dec: 6, b64: 'G', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '111100', dec: 60, b64: '8', isPad: false, + groupId: '', + bitGroups: [], }, { bin: '', - dec: null, + dec: 0, b64: '=', isPad: true, + groupId: '', + bitGroups: [], }, ], }, diff --git a/apps/svelte-base64/tests/e2e.test.ts b/apps/svelte-base64/tests/e2e.test.ts index 3812a67e..620c9473 100644 --- a/apps/svelte-base64/tests/e2e.test.ts +++ b/apps/svelte-base64/tests/e2e.test.ts @@ -4,14 +4,14 @@ import { chromium } from 'playwright'; import type { PreviewServer } from 'vite'; import { preview } from 'vite'; import { afterAll, afterEach, beforeAll, beforeEach, describe, test } from 'vitest'; -import { AlgoDemoTester } from './algoDemoTester'; +import { AlgorithmDemoPage } from './algorithmDemoPage'; // eslint-disable-next-line @typescript-eslint/require-await describe('verify encoding process using ascii-encoded strings', async () => { let server: PreviewServer; let browser: Browser; let page: Page; - let pageTester: AlgoDemoTester | null; + let algorithmDemoPage: AlgorithmDemoPage | null; beforeAll(async () => { server = await preview({ preview: { port: 4500 } }); @@ -20,11 +20,11 @@ describe('verify encoding process using ascii-encoded strings', async () => { beforeEach(async () => { browser = await chromium.launch({ headless: true }); page = await browser.newPage(); - pageTester = new AlgoDemoTester(page); + algorithmDemoPage = new AlgorithmDemoPage(page); }); afterEach(async () => { - pageTester = null; + algorithmDemoPage = null; await page.close(); await browser.close(); }); @@ -36,559 +36,559 @@ describe('verify encoding process using ascii-encoded strings', async () => { }); test('encode ascii string, execute all steps manually', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('test'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('test'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); for await (const _ of Array.from({ length: 4 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); for await (const _ of Array.from({ length: 8 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'verifyResults', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'verifyResults', substate: '' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }, 60_000); test('encode ascii string, execute all steps with autoplay', async () => { - if (!pageTester) return; - await pageTester.goto(); - - await pageTester.changeInputText('test'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); - - await pageTester.startAutoplay(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'autoPlayEncodeByte' }); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'autoPlayIdle' }); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'autoPlayCreateInputChunk' }); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'autoPlayIdle' }); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'autoPlayCreateOutputChunk' }); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'autoPlayEncodeBase64' }); - await pageTester.verifyMachineState({ state: 'verifyResults', substate: '' }); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); + + await algorithmDemoPage.changeInputText('test'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); + + await algorithmDemoPage.startAutoplay(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'autoPlayEncodeByte' }); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'autoPlayIdle' }); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'autoPlayCreateInputChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'autoPlayIdle' }); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'autoPlayCreateOutputChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'autoPlayEncodeBase64' }); + await algorithmDemoPage.verifyMachineState({ state: 'verifyResults', substate: '' }); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode ascii string, skip demo', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('test'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('test'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode ascii string, validation error', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.startAutoplay(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.startAutoplay(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('do§'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('do§'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('dog'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('dog'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode ascii string, with symbol characters', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('test&^%#*&()'); - await pageTester.selectAsciiInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('test&^%#*&()'); + await algorithmDemoPage.selectAsciiInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode hex string, execute all steps manually', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('0d47bc37af'); - await pageTester.selectHexInputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('0d47bc37af'); + await algorithmDemoPage.selectHexInputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'verifyResults', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'verifyResults', substate: '' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode hex string, validation error', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('746573t'); - await pageTester.selectHexInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('746573t'); + await algorithmDemoPage.selectHexInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('74657'); - await pageTester.selectHexInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('74657'); + await algorithmDemoPage.selectHexInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('74657374'); - await pageTester.selectHexInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('74657374'); + await algorithmDemoPage.selectHexInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode bin string, execute all steps manually', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('01110100011001010111001101110100'); - await pageTester.selectBinaryInputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('01110100011001010111001101110100'); + await algorithmDemoPage.selectBinaryInputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'verifyResults', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'verifyResults', substate: '' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode bin string, skip demo', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('01110100011001010111001101110100'); - await pageTester.selectBinaryInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('01110100011001010111001101110100'); + await algorithmDemoPage.selectBinaryInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode bin string, validation error', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('test'); - await pageTester.selectBinaryInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('test'); + await algorithmDemoPage.selectBinaryInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.startAutoplay(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.startAutoplay(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('0101'); - await pageTester.selectBinaryInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('0101'); + await algorithmDemoPage.selectBinaryInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'error' }); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'error' }); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('01110100011001010111001101110100'); - await pageTester.selectBinaryInputEncoding(); - await pageTester.selectBase64UrlOutputEncoding(); + await algorithmDemoPage.changeInputText('01110100011001010111001101110100'); + await algorithmDemoPage.selectBinaryInputEncoding(); + await algorithmDemoPage.selectBase64UrlOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode utf8 string, execute all steps manually', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('🦦👨‍🌾🫥🏃🏿‍♀️☝🏾'); - await pageTester.selectUtf8InputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('🦦👨‍🌾🫥🏃🏿‍♀️☝🏾'); + await algorithmDemoPage.selectUtf8InputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'idle' }); for await (const _ of Array.from({ length: 43 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'encodeByte' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeInput', substate: 'explainByteMapping' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'regularIdle' }); for await (const _ of Array.from({ length: 14 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createInputChunk' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createInputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'regularIdle' }); for await (const _ of Array.from({ length: 14 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createOutputChunk' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'explainPadCharacter' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'createOutputChunks', substate: 'createLastPaddedChunk' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'idle' }); for await (const _ of Array.from({ length: 60 }, (_, i) => i)) { - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'encodeOutput', substate: 'encodeBase64' }); } - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'verifyResults', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'verifyResults', substate: '' }); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); test('encode multiple utf8 strings, mix of ascii and utf8', async () => { - if (!pageTester) return; - await pageTester.goto(); + if (!algorithmDemoPage) return; + await algorithmDemoPage.goto(); - await pageTester.changeInputText('🦦👨‍🌾🫥🏃🏿‍♀️☝🏾'); - await pageTester.selectUtf8InputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('🦦👨‍🌾🫥🏃🏿‍♀️☝🏾'); + await algorithmDemoPage.selectUtf8InputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); - await pageTester.goToFirstStep(); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToFirstStep(); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('∑ßåœ ≈ ∆c'); - await pageTester.selectUtf8InputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('∑ßåœ ≈ ∆c'); + await algorithmDemoPage.selectUtf8InputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); - await pageTester.goToFirstStep(); - await pageTester.verifyMachineState({ state: 'inactive', substate: '' }); + await algorithmDemoPage.goToFirstStep(); + await algorithmDemoPage.verifyMachineState({ state: 'inactive', substate: '' }); - await pageTester.changeInputText('日本語文字列'); - await pageTester.selectUtf8InputEncoding(); - await pageTester.selectBase64StandardOutputEncoding(); + await algorithmDemoPage.changeInputText('日本語文字列'); + await algorithmDemoPage.selectUtf8InputEncoding(); + await algorithmDemoPage.selectBase64StandardOutputEncoding(); - await pageTester.goToNextStep(); - await pageTester.verifyMachineState({ state: 'validateInputText', substate: 'success' }); + await algorithmDemoPage.goToNextStep(); + await algorithmDemoPage.verifyMachineState({ state: 'validateInputText', substate: 'success' }); - await pageTester.goToLastStep(); - await pageTester.verifyMachineState({ state: 'finished', substate: '' }); + await algorithmDemoPage.goToLastStep(); + await algorithmDemoPage.verifyMachineState({ state: 'finished', substate: '' }); }); }); From e14dfb0ac35ff786c54515b90496f6e7de823835 Mon Sep 17 00:00:00 2001 From: Aaron Luna Date: Sun, 28 Jan 2024 15:11:20 -0800 Subject: [PATCH 5/5] style(svelte-base64): :sparkles: minor visual tweaks and fixes for all components --- apps/svelte-base64/.eslintrc.cjs | 50 +++-- apps/svelte-base64/src/app.html | 2 +- apps/svelte-base64/src/global.css | 196 ++++++++---------- .../DemoIntro/DetailsSummary.svelte | 1 + .../Sections/KeyboardShortcuts.svelte | 8 +- .../Sections/StringInputEncoding1.svelte | 2 +- .../Sections/StringInputEncoding2.svelte | 2 +- .../Icons/KeyboardIcons/ArrowKey.svelte | 2 +- .../lib/components/InputForm/InputForm.svelte | 12 +- .../src/lib/components/InputTextBox.svelte | 4 +- .../src/lib/components/Modal.svelte | 8 +- apps/svelte-base64/src/lib/types/AppStore.ts | 3 +- .../src/lib/types/Base64ByteMap.ts | 4 +- .../src/lib/types/DecoderInput.ts | 12 +- .../src/lib/types/EncoderInput.ts | 20 +- .../svelte-base64/src/lib/types/HexByteMap.ts | 10 +- apps/svelte-base64/src/lib/types/alias.ts | 11 - apps/svelte-base64/src/lib/types/index.ts | 28 ++- apps/svelte-base64/src/lib/types/utf8.ts | 2 +- apps/svelte-base64/svelte.config.js | 6 +- 20 files changed, 182 insertions(+), 201 deletions(-) diff --git a/apps/svelte-base64/.eslintrc.cjs b/apps/svelte-base64/.eslintrc.cjs index 1e0eea12..a844ce15 100644 --- a/apps/svelte-base64/.eslintrc.cjs +++ b/apps/svelte-base64/.eslintrc.cjs @@ -1,5 +1,7 @@ module.exports = { + extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:svelte/recommended', 'prettier'], parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], parserOptions: { ecmaVersion: '2020', sourceType: 'module', @@ -12,23 +14,26 @@ module.exports = { es2021: true, node: true, }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - ], - globals: { - NodeJS: true, - }, - plugins: ['svelte3', '@typescript-eslint'], - ignorePatterns: ['*.cjs'], - settings: { - 'svelte3/typescript': true, + rules: { + // Note: you must disable the base rule as it can report incorrect errors + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + }, + ], }, overrides: [ { files: ['*.svelte'], - processor: 'svelte3/svelte3', + parser: 'svelte-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + }, }, { files: ['*.ts'], @@ -37,4 +42,23 @@ module.exports = { }, }, ], + settings: { + svelte: { + ignoreWarnings: ['svelte/no-at-html-tags'], + compileOptions: { + postcss: { + configFilePath: './postcss.config.cjs', + }, + }, + kit: { + files: { + routes: 'src/routes', + }, + }, + }, + }, + globals: { + NodeJS: true, + }, + ignorePatterns: ['*.cjs'], }; diff --git a/apps/svelte-base64/src/app.html b/apps/svelte-base64/src/app.html index 6e8f6f0d..859ac6dc 100644 --- a/apps/svelte-base64/src/app.html +++ b/apps/svelte-base64/src/app.html @@ -1,4 +1,4 @@ - + diff --git a/apps/svelte-base64/src/global.css b/apps/svelte-base64/src/global.css index 87828b7b..6e6e7a18 100644 --- a/apps/svelte-base64/src/global.css +++ b/apps/svelte-base64/src/global.css @@ -180,148 +180,86 @@ main.decode { } main { - --pri-color: hsl( - var(--pri-h) - var(--pri-s) - var(--pri-l) / - var(--pri-a) - ); - --sec-color: hsl( - var(--sec-h) - var(--sec-s) - var(--sec-l) / - var(--sec-a) - ); + --pri-color: hsl(var(--pri-h) var(--pri-s) var(--pri-l) / var(--pri-a)); + --sec-color: hsl(var(--sec-h) var(--sec-s) var(--sec-l) / var(--sec-a)); /* Form Title */ --form-title-text-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.3)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.3)), 0) ); - --form-title-text-shadow-color: hsl( - var(--sec-h) - var(--sec-s) - var(--sec-l) / - max(calc(var(--pri-a) - 0.75), 0) - ); + --form-title-text-shadow-color: hsl(var(--sec-h) var(--sec-s) var(--sec-l) / max(calc(var(--pri-a) - 0.75), 0)); /* Drop Down Lists */ - --dropdown-bg-color: hsl( - var(--pri-h) - max(calc(var(--pri-s) - 48%), 0%) - var(--pri-l) / - var(--pri-a) - ); + --dropdown-bg-color: hsl(var(--pri-h) max(calc(var(--pri-s) - 48%), 0%) var(--pri-l) / var(--pri-a)); --dropdown-text-color: var(--black2); --dropdown-border-color: hsl( - var(--pri-h) - max(calc(var(--pri-s) - 33%), 0%) - min(calc(var(--pri-l) + 5%), 100%) / - var(--pri-a) + var(--pri-h) max(calc(var(--pri-s) - 33%), 0%) min(calc(var(--pri-l) + 5%), 100%) / var(--pri-a) ); --selected-item-bg-color: hsl( - var(--pri-h) - max(calc(var(--pri-s) - 3%), 0%) - min(calc(var(--pri-l) + 10%), 100%) / - var(--pri-a) + var(--pri-h) max(calc(var(--pri-s) - 3%), 0%) min(calc(var(--pri-l) + 10%), 100%) / var(--pri-a) ); /* Algorithm Demo Nav Buttons (Manual Mode) */ --nav-button-text-color: var(--black2); --nav-button-bg-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.55)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.55)), 0) ); --nav-button-border-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.3)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.3)), 0) ); --nav-button-hover-text-color: var(--black4); --nav-button-hover-bg-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.3)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.3)), 0) ); --nav-button-active-text-color: var(--black4); --nav-button-active-bg-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.15)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.15)), 0) ); --nav-button-active-border-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.15)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.15)), 0) ); /* Algorithm Demo Nav Buttons (Auto Play Mode) */ --nav-button-autoplay-text-color: var(--black4); - --nav-button-autoplay-bg-color: hsl( - var(--sec-h) - var(--sec-s) - var(--sec-l) / - max((calc(var(--sec-a) - 0.15)), 0) - ); - --nav-button-autoplay-border-color: hsl( - var(--sec-h) - var(--sec-s) - var(--sec-l) / - max((calc(var(--sec-a) - 0.15)), 0) - ); + --nav-button-autoplay-bg-color: hsl(var(--sec-h) var(--sec-s) var(--sec-l) / max((calc(var(--sec-a) - 0.15)), 0)); + --nav-button-autoplay-border-color: hsl(var(--sec-h) var(--sec-s) var(--sec-l) / max((calc(var(--sec-a) - 0.15)), 0)); --nav-button-autoplay-hover-text-color: var(--black4); --nav-button-autoplay-hover-bg-color: hsl( - var(--sec-h) - min(calc(var(--sec-s) + 7%), 100%) - min(calc(var(--sec-l) + 10%), 100%) / - max((calc(var(--pri-a) - 0.3)), 0) + var(--sec-h) min(calc(var(--sec-s) + 7%), 100%) min(calc(var(--sec-l) + 10%), 100%) / + max((calc(var(--pri-a) - 0.3)), 0) ); --nav-button-autoplay-active-text-color: var(--black4); --nav-button-autoplay-active-bg-color: hsl( - var(--sec-h) - min(calc(var(--sec-s) + 7%), 100%) - min(calc(var(--sec-l) + 10%), 100%) / - max((calc(var(--sec-a) - 0.15)), 0) + var(--sec-h) min(calc(var(--sec-s) + 7%), 100%) min(calc(var(--sec-l) + 10%), 100%) / + max((calc(var(--sec-a) - 0.15)), 0) ); --nav-button-autoplay-active-border-color: hsl( - var(--sec-h) - min(calc(var(--sec-s) + 7%), 100%) - min(calc(var(--sec-l) + 10%), 100%) / - max((calc(var(--sec-a) - 0.15)), 0) + var(--sec-h) min(calc(var(--sec-s) + 7%), 100%) min(calc(var(--sec-l) + 10%), 100%) / + max((calc(var(--sec-a) - 0.15)), 0) ); --nav-button-autoplay-disabled-text-color: var(--dark-gray4); --nav-button-autoplay-disabled-bg-color: hsl( - var(--sec-h) - var(--sec-s) - min(calc(var(--sec-l) + 17%), 100%) / - max((calc(var(--sec-a) - 0.75)), 0) + var(--sec-h) var(--sec-s) min(calc(var(--sec-l) + 17%), 100%) / max((calc(var(--sec-a) - 0.75)), 0) ); --nav-button-autoplay-disabled-border-color: var(--nav-button-autoplay-border-color); --nav-button-stop-autoplay-text-color: var(--black2); --nav-button-stop-autoplay-bg-color: hsl( - var(--sec-h) - var(--sec-s) - var(--sec-l) / - max((calc(var(--sec-a) - 0.55)), 0) + var(--sec-h) var(--sec-s) var(--sec-l) / max((calc(var(--sec-a) - 0.55)), 0) ); --nav-button-stop-autoplay-border-color: var(--nav-button-autoplay-border-color); /* Disabled Button */ --button-disabled-text-color: var(--dark-gray4); --button-disabled-bg-color: hsl( - var(--pri-h) - min(calc(var(--pri-s) + 7%), 100%) - min(calc(var(--pri-l) + 35%), 100%) / - max((calc(var(--pri-a) - 0.75)), 0) + var(--pri-h) min(calc(var(--pri-s) + 7%), 100%) min(calc(var(--pri-l) + 35%), 100%) / + max((calc(var(--pri-a) - 0.75)), 0) ); --button-disabled-border-color: var(--nav-button-border-color); @@ -345,16 +283,18 @@ main { /* Select List */ --select-list-dropdown-background-color: var(--dropdown-bg-color, var(--white2)); --select-list-dropdown-text-color: var(--dropdown-text-color, var(--black2)); - --select-list-dropdown-border-color: var(--dropdown-border-color, var(--light-gray2)); + --select-list-border-color: var(--dropdown-border-color, var(--light-gray2)); --select-list-open-button-background-color: var(--list-button-bg-color, var(--white2)); --select-list-open-button-text-color: var(--list-button-text-color, var(--black2)); --select-list-open-button-border-color: var(--list-button-border-color, var(--light-gray2)); - --select-list-open-button-hover-background-color: var(--list-button-hover-bg-color, var(--white4)); + --select-list-open-button-background-color-hover: var(--list-button-hover-bg-color, var(--white4)); + --select-list-open-button-text-color-hover: var(--nav-button-hover-text-color, var(--black2)); + --select-list-border-color-hover: var(--nav-button-border-color, var(--light-gray2)); --select-list-border-radius: 6px; --select-list-dropdown-border-radius: 0.375rem; - --select-list-selected-item-background-color: var(--selected-item-bg-color, var(--white4)); + --select-list-menu-item-background-color-hover: var(--selected-item-bg-color, var(--white4)); --select-list-height: 33px; --select-list-font-size: 0.875rem; --select-list-disabled-text-color: var(--list-button-disabled-text-color, var(--dark-gray2)); @@ -424,7 +364,7 @@ textarea { box-sizing: border-box; } -.details-content>*, +.details-content > *, #demo-text p { line-height: 1.6; font-size: 0.825rem; @@ -432,14 +372,14 @@ textarea { color: var(--light-gray2); } -#demo-text .details-content>p, -#demo-text .details-content>p:first-child, -#demo-text .details-content>p:last-child, -#demo-text .details-content>p:last-of-type:not(:only-of-type) { +#demo-text .details-content > p, +#demo-text .details-content > p:first-child, +#demo-text .details-content > p:last-child, +#demo-text .details-content > p:last-of-type:not(:only-of-type) { margin: 0 0 0 1rem; } -#demo-text details:last-child .details-content>p:last-child { +#demo-text details:last-child .details-content > p:last-child { margin: 0 0 0.5rem 1rem; } @@ -478,7 +418,7 @@ button { } #demo-text .legend strong { - color: inherit + color: inherit; } #demo-text code { @@ -639,12 +579,27 @@ button { } .char, +.base64 { + color: var(--light-gray1); +} + .ascii, .hex { color: var(--pri-color); } -.base64, +#input-hex .byte-id { + width: 18.2px; +} + +#input-hex .char { + width: 11.5px; +} + +#output-b64 .b64Char-id { + width: 15.5px; +} + .dec { color: var(--sec-color); } @@ -856,11 +811,11 @@ button { height: auto; } -div[id*="modal"] .help-docs, -div[id*="modal"] .help-docs button:hover, -div[id*="modal"] .help-docs button:focus, -div[id*="modal"] .help-docs button:active, -div[id*="modal"] .help-docs button:active:focus { +div[id*='modal'] .help-docs, +div[id*='modal'] .help-docs button:hover, +div[id*='modal'] .help-docs button:focus, +div[id*='modal'] .help-docs button:active, +div[id*='modal'] .help-docs button:active:focus { background-color: transparent; } @@ -882,7 +837,6 @@ div[id*="modal"] .help-docs button:active:focus { .help-docs button.nav:active, .help-docs button.nav:active:focus { color: var(--nav-button-active-bg-color); - } .help-docs-content { @@ -946,11 +900,15 @@ div[id*="modal"] .help-docs button:active:focus { } .help-docs-nav .nav-link.current-section { - box-shadow: inset 0 -1px 0 0 var(--help-docs-bg-color), inset 0 -3px 0 0 var(--nav-button-hover-bg-color); + box-shadow: + inset 0 -1px 0 0 var(--help-docs-bg-color), + inset 0 -3px 0 0 var(--nav-button-hover-bg-color); } .help-docs-nav .nav-link.current-section:hover { - box-shadow: inset 0 -1px 0 0 var(--help-docs-bg-color), inset 0 -3px 0 0 var(--nav-button-active-bg-color); + box-shadow: + inset 0 -1px 0 0 var(--help-docs-bg-color), + inset 0 -3px 0 0 var(--nav-button-active-bg-color); } .help-docs p { @@ -1002,6 +960,7 @@ div[id*="modal"] .help-docs button:active:focus { flex-flow: column nowrap; gap: 0.5rem; padding: 0.5rem; + line-height: 1.4; background-color: var(--modal-dialog-bg-color); border-top-left-radius: 6px; border-top-right-radius: 6px; @@ -1338,7 +1297,6 @@ div[id*="modal"] .help-docs button:active:focus { } @media screen and (min-width: 764px) { - html, body { background-color: var(--dark-gray1); @@ -1349,7 +1307,7 @@ div[id*="modal"] .help-docs button:active:focus { padding: 1px 2px; } - details>summary { + details > summary { font-size: 1.1rem; } @@ -1358,7 +1316,7 @@ div[id*="modal"] .help-docs button:active:focus { margin: 0; } - .details-content>*, + .details-content > *, #demo-text p { line-height: 1.5; font-size: 0.9rem; @@ -1439,6 +1397,14 @@ div[id*="modal"] .help-docs button:active:focus { width: 12px; } + #input-hex .byte-id { + width: 19.2px; + } + + #output-b64 .b64Char-id { + width: 16.7px; + } + .help-docs { font-size: 13px; } @@ -1513,4 +1479,4 @@ div[id*="modal"] .help-docs button:active:focus { .b64-ref-content { font-size: 0.8rem; } -} \ No newline at end of file +} diff --git a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoIntro/DetailsSummary.svelte b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoIntro/DetailsSummary.svelte index 4fe461eb..e2f52948 100644 --- a/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoIntro/DetailsSummary.svelte +++ b/apps/svelte-base64/src/lib/components/AlgorithmDemo/DemoIntro/DetailsSummary.svelte @@ -14,6 +14,7 @@ diff --git a/apps/svelte-base64/src/lib/components/InputForm/InputForm.svelte b/apps/svelte-base64/src/lib/components/InputForm/InputForm.svelte index f9d5e90e..de0ac1be 100644 --- a/apps/svelte-base64/src/lib/components/InputForm/InputForm.svelte +++ b/apps/svelte-base64/src/lib/components/InputForm/InputForm.svelte @@ -31,19 +31,19 @@ ? `${defaultFlexStyles} flex-flow: row nowrap;` : `${defaultFlexStyles} flex-flow: column nowrap;` : $app.isMobileDisplay - ? `${defaultFlexStyles} flex-flow: column nowrap; ` - : `${defaultFlexStyles} flex-flow: row nowrap;`; + ? `${defaultFlexStyles} flex-flow: column nowrap; ` + : `${defaultFlexStyles} flex-flow: row nowrap;`; $: defaultGridStyles = 'display: grid; gap: 0.5rem; padding: 0.25rem 0.5rem 0.5rem 0.5rem;'; $: inputTextEncodingStylesGrid = $app.isDefaultDisplay ? `${defaultGridStyles} grid-template-columns: 75px 1fr; grid-template-rows: auto auto;` : $app.isMobileDisplay - ? `${defaultGridStyles} grid-template-columns: 75px 75px 75px 1fr; grid-template-rows: auto;` - : `${defaultGridStyles} grid-template-columns: repeat(4, auto); grid-template-rows: auto;`; + ? `${defaultGridStyles} grid-template-columns: 75px 75px 75px 1fr; grid-template-rows: auto;` + : `${defaultGridStyles} grid-template-columns: repeat(4, auto); grid-template-rows: auto;`; $: outputBase64EncodingStylesGrid = $app.isDefaultDisplay ? `${defaultGridStyles} grid-template-columns: 1fr; grid-template-rows: auto auto;` : $app.isMobileDisplay - ? `${defaultGridStyles} grid-template-columns: 75px 1fr; grid-template-rows: auto;` - : `${defaultGridStyles} grid-template-columns: repeat(2, auto); grid-template-rows: auto;`; + ? `${defaultGridStyles} grid-template-columns: 75px 1fr; grid-template-rows: auto;` + : `${defaultGridStyles} grid-template-columns: repeat(2, auto); grid-template-rows: auto;`; $: inputBase64EncodingStylesGrid = `${defaultGridStyles} grid-template-columns: auto 1fr; grid-template-rows: auto;`; $: state.changeInputText(inputText); $: if ($state.resetPerformed) { diff --git a/apps/svelte-base64/src/lib/components/InputTextBox.svelte b/apps/svelte-base64/src/lib/components/InputTextBox.svelte index 0d28f162..a3a60c7f 100644 --- a/apps/svelte-base64/src/lib/components/InputTextBox.svelte +++ b/apps/svelte-base64/src/lib/components/InputTextBox.svelte @@ -1,5 +1,5 @@