Skip to content

Commit

Permalink
UI redesign pt1 (#39)
Browse files Browse the repository at this point in the history
* Implement new layout for Tools page
- Refactor ToolsView component with new layout
- Added sidebar functionality with animation

* Update Header logo

* Implement ToolsView mobile layout

* update tools page design on mobile

* Implement new design for JSON Formatter utility page
- bring in and set up ace code editor for JSON input
- enable syntax highlighting on JSON input to provide valuable user feedback when JSON is not valid
- bring in vue-debounce to debounce auto-convert utilities
- bring in vue-toastify to provide user valuable toast messages when certain actions are performed

* highlight current page in navigation bar depending on route

* add TwoPaneLayout

* refactor utilities to use TwoPaneLayout

* align color converter conversion boxes

* scroll to top of page on navigation

* fix StringInspector prompts
* wrap PHP>JSON conversion in try/catch so we don't clog up the console

* Fix tests
  • Loading branch information
JStruk committed Jan 25, 2024
1 parent fbf222c commit b893114
Show file tree
Hide file tree
Showing 36 changed files with 666 additions and 278 deletions.
20 changes: 20 additions & 0 deletions ace-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import ace from 'ace-builds'

import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url'
import themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url'
import workerBaseUrl from 'ace-builds/src-noconflict/worker-base?url'
import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'
import snippetsJsonUrl from 'ace-builds/src-noconflict/snippets/json?url'
import 'ace-builds/src-noconflict/ext-language_tools'

ace.config.setModuleUrl('ace/mode/json', modeJsonUrl)

ace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl)

ace.config.setModuleUrl('ace/mode/base', workerBaseUrl)

ace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl)

ace.config.setModuleUrl('ace/snippets/json', snippetsJsonUrl)

ace.require('ace/ext/language_tools')
2 changes: 1 addition & 1 deletion cypress/e2e/navigation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Navigation', () => {
it('can visit the tools page', () => {
cy.visit('/tools')

cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools/json-formatter`)
cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools`)

// TODO: dynamically check for util tabs based on registry of utils
cy.contains('JSON Format')
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/pages/HomeView.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ describe('HomeView', () => {
cy.visit('/')
cy.contains('View Tools').click()

cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools/json-formatter`)
cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools`)
})

it('allows the user to go to the Tools page via navbar', () => {
cy.visit('/')
cy.contains('Tools').click()

cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools/json-formatter`)
cy.url().should('be.equal', `${Cypress.config('baseUrl')}/tools`)
})
})
6 changes: 3 additions & 3 deletions cypress/e2e/utils/PHPArrayToJson.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ describe('PHP Array To Json', () => {
const phpArray = `["${key}" => "${value}"]`

it('should allow the user to enter text', () => {
cy.get('textarea').type(phpArray)
cy.get('[aria-label="php-array-input"]').filter(':visible').type(phpArray)
})

it('should display the results of the inspected string', () => {
cy.get('textarea').type(phpArray)
cy.get('[aria-label="php-array-input"]').filter(':visible').type(phpArray)

cy.get('button').contains('Convert').click()
cy.wait(310)

cy.contains(`"${key}":"${value}"`)
})
Expand Down
12 changes: 9 additions & 3 deletions cypress/e2e/utils/StringInspector.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ describe('String Inspector', () => {


it('should allow the user to enter text', () => {
cy.get('textarea[aria-label="string-inspector"]').type(text, { scrollBehavior: 'center' })
cy.get('textarea[aria-label="string-inspector"]')
.filter(':visible')
.type(text, { scrollBehavior: 'center' })
})

it('should display the results of the inspected string', () => {
cy.get('textarea[aria-label="string-inspector"]').type(sentence, { scrollBehavior: 'center' })
cy.get('textarea[aria-label="string-inspector"]')
.filter(':visible')
.type(sentence, { scrollBehavior: 'center' })

const inspectorResult: InspectionResult = inspect(sentence)

Expand All @@ -25,7 +29,9 @@ describe('String Inspector', () => {
})

it('should display the word distribution for the inspected string', function () {
cy.get('textarea[aria-label="string-inspector"]').type(sentence, { scrollBehavior: 'center' })
cy.get('textarea[aria-label="string-inspector"]')
.filter(':visible')
.type(sentence, { scrollBehavior: 'center' })

const inspectorResult: InspectionResult = inspect(sentence)

Expand Down
16 changes: 12 additions & 4 deletions cypress/e2e/utils/base64Decode.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ describe('Base64 Decoder', () => {
const text: string = 'Rm9vYmFy'

it('should allow the user to enter text to decode', () => {
cy.get('textarea[aria-label="input-to-decode"]').type(text)
cy.get('textarea[aria-label="input-to-decode"]')
.filter(':visible')
.type(text)
})

it('should display the decoded text', () => {
cy.get('textarea[aria-label="input-to-decode"]').type(text)
cy.get('button[aria-label="decode-text"]').click()
cy.get('textarea[aria-label="input-to-decode"]')
.filter(':visible')
.type(text)

const decodedText: string = Base64Decode(text)
cy.get('textarea[aria-label="decoded-text"]').should('have.value', decodedText)
cy.wait(310)

cy.get('textarea[aria-label="decoded-text"]')
.filter(':visible')
.should('have.value', decodedText)
})

})
16 changes: 11 additions & 5 deletions cypress/e2e/utils/base64Encode.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ describe('Base64 Encoder', () => {
const text: string = 'idk this is definitely some text'

it('should allow the user to enter text to encode', () => {
cy.get('textarea[aria-label="input-to-encode"]').type(text)
cy.get('textarea[aria-label="input-to-encode"]')
.filter(':visible')
.type(text)
})

it('should display the encoded text', () => {
cy.get('textarea[aria-label="input-to-encode"]').type(text)
cy.get('button[aria-label="encode-text"]').click()
cy.get('textarea[aria-label="input-to-encode"]')
.filter(':visible')
.type(text)

const encodedText: string = Base64Encode(text)
cy.get('textarea[aria-label="encoded-text"]').should('have.value', encodedText)
cy.wait(310)
cy.get('textarea[aria-label="encoded-text"]')
.filter(':visible')
.should('have.value', encodedText)
})

})
Empty file.
29 changes: 22 additions & 7 deletions cypress/e2e/utils/csvtojson.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,37 @@ describe('CSV to JSON', () => {
})

it('should allow the user to type text into textarea', () => {
cy.get('textarea[placeholder="CSV Data"]').type('I am the walrus', { scrollBehavior: 'center' })
cy.get('textarea[placeholder="CSV Data"]')
.filter(':visible')
.type('I am the walrus', { scrollBehavior: 'center' })
})

it('should accept user CSV and output converted JSON', () => {
const CSVData = "Name,Age,Height\nJoe,25,5'10\nMike,30,6'0"

cy.get('textarea[placeholder="CSV Data"]').type(CSVData, { scrollBehavior: 'center' })
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="CSV Data"]')
.filter(':visible')
.type(CSVData, { scrollBehavior: 'center' })

const expectedJSON = CSVToJSON(CSVData)
cy.get('textarea[placeholder="JSON format"]').invoke('val').should('equal', expectedJSON)
cy.wait(310)

cy.get('textarea[placeholder="JSON format"]')
.filter(':visible')
.invoke('val')
.should('equal', expectedJSON)
})

it('should return an empty array if the CSV data cannot be parsed', () => {
cy.get('textarea[placeholder="CSV Data"]').type('I am the walrus', { scrollBehavior: 'center' })
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="JSON format"]').invoke('val').should('equal', '[]')
cy.get('textarea[placeholder="CSV Data"]')
.filter(':visible')
.type('I am the walrus', { scrollBehavior: 'center' })

cy.wait(310)

cy.get('textarea[placeholder="JSON format"]')
.filter(':visible')
.invoke('val')
.should('equal', '[]')
})
})
8 changes: 6 additions & 2 deletions cypress/e2e/utils/dateConverter.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ describe('Unix Epoch to Date', () => {
})

it('should allow the user to enter a timestamp', () => {
cy.get('input').type('I am the walrus')
cy.get('input')
.filter(':visible')
.type('I am the walrus')
})

it('displays the date strings', () => {
const timestamp = '1674595801793'

cy.get('input').type(timestamp)
cy.get('input')
.filter(':visible')
.type(timestamp)

const formattedDates = unixEpochToDate(parseInt(timestamp))
cy.contains(`"iso":"${formattedDates.iso}"`)
Expand Down
23 changes: 17 additions & 6 deletions cypress/e2e/utils/jsontocsv.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,34 @@ describe('CSV to JSON', () => {
})

it('should allow the user to type text into textarea', () => {
cy.get('textarea[placeholder="JSON Data"]').type('I am the walrus')
cy.get('textarea[placeholder="JSON Data"]')
.filter(':visible')
.type('I am the walrus')
})

it('should accept user CSV and output converted JSON', () => {
const JSONData = '[{"name": "John Doe", "age": "15"}]'

cy.get('textarea[placeholder="JSON Data"]').type(JSONData, { parseSpecialCharSequences: false })
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="JSON Data"]')
.filter(':visible')
.type(JSONData, { parseSpecialCharSequences: false })

cy.wait(310)

const expectedCSV = JSONtoCSV(JSONData)
cy.get('textarea[placeholder="CSV format"]').invoke('val').should('equal', expectedCSV)
})


it('should return an empty array if the CSV data cannot be parsed', () => {
cy.get('textarea[placeholder="JSON Data"]').type('I am the walrus')
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="CSV format"]').invoke('val').should('equal', '')
cy.get('textarea[placeholder="JSON Data"]')
.filter(':visible')
.type('I am the walrus')

cy.wait(310)
cy.get('textarea[placeholder="CSV format"]')
.filter(':visible')
.invoke('val')
.should('equal', '')
})
})
41 changes: 30 additions & 11 deletions cypress/e2e/utils/lineSort.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,47 @@ describe('LineSort', () => {
const duplicateText: string = 'c\nc\nc\nb\na'

it('should allow the user to enter text to sort', () => {
cy.get('textarea[aria-label="input-to-sort"]').type(text)
cy.get('textarea[aria-label="input-to-sort"]')
.filter(':visible')
.type(text)
})

it('should display the sorted text', () => {
cy.get('textarea[aria-label="input-to-sort"]').type(text)
cy.get('button[aria-label="sort-button"]').click()
cy.get('textarea[aria-label="input-to-sort"]')
.filter(':visible')
.type(text)

const sortedText: string = lineSort(text, false)
cy.get('textarea[aria-label="sorted-text"]').should('have.value', sortedText)
cy.wait(310)
cy.get('textarea[aria-label="sorted-text"]')
.filter(':visible')
.should('have.value', sortedText)
})

it('should remove duplicate lines and sort', () => {
cy.get('textarea[aria-label="input-to-sort"]').type(duplicateText)
cy.get('button[aria-label="sort-button"]').click()
cy.get('textarea[aria-label="input-to-sort"]')
.filter(':visible')
.type(duplicateText)

const sortedText: string = lineSort(duplicateText)
cy.get('textarea[aria-label="sorted-text"]').should('have.value', sortedText)
cy.wait(310)
cy.get('textarea[aria-label="sorted-text"]')
.filter(':visible')
.should('have.value', sortedText)
})

it('should not remove duplicate lines if not selected', () => {
cy.get('textarea[aria-label="input-to-sort"]').type(duplicateText)
cy.get('input[aria-label="remove-duplicates-checkbox"]').click()
cy.get('button[aria-label="sort-button"]').click()
cy.get('textarea[aria-label="input-to-sort"]')
.filter(':visible')
.type(duplicateText)
cy.get('input[aria-label="remove-duplicates-checkbox"]')
.filter(':visible')
.click()

cy.wait(310)
const sortedText: string = lineSort(duplicateText, false)
cy.get('textarea[aria-label="sorted-text"]').should('have.value', sortedText)
cy.get('textarea[aria-label="sorted-text"]')
.filter(':visible')
.should('have.value', sortedText)
})
})
16 changes: 13 additions & 3 deletions cypress/e2e/utils/loremipsum.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@ describe('Lorem Ipsum Generator', () => {
})

it('should allow user to enter number of paragraphs', () => {
cy.get('input[type="number"]').type('3')
cy.get('input[type="number"]')
.filter(':visible')
.type('3')
})

it('should generate lorem ipsum text', () => {
cy.get('input[type="number"]').type('3')
cy.get('input[type="number"]')
.filter(':visible')
.type('3')
cy.contains('Generate').click()

cy.get('[aria-label="generated-lorem-ipsum"]')
.filter(':visible')
.should('not.have.value', ':empty')
})

it('should populate textarea with generated lorem ipsum text', () => {
cy.get('input[type="number"]').type('3')
cy.get('input[type="number"]')
.filter(':visible')
.type('3')
cy.contains('Generate').click()
cy.get('textarea').invoke('val').should('not.be.empty')
})
Expand Down
Loading

0 comments on commit b893114

Please sign in to comment.