diff --git a/cypress.json b/cypress.json index 6fda274..4fd2057 100644 --- a/cypress.json +++ b/cypress.json @@ -1,3 +1,3 @@ { - "baseUrl": "http://localhost:3001" + "baseUrl": "http://localhost:3001/test" } \ No newline at end of file diff --git a/cypress/integration/choices_spec.js b/cypress/integration/choices_spec.js deleted file mode 100644 index c68b20f..0000000 --- a/cypress/integration/choices_spec.js +++ /dev/null @@ -1,169 +0,0 @@ -describe('Choices', () => { - beforeEach(() => { - cy.visit('/test.html'); - }); - - describe('text element', () => { - const textInput = 'testing'; - - describe('choices enabled', () => { - describe('adding choices', () => { - it('allows me to input choices', () => { - cy.get('.choices') - .first() - .find('.choices__input--cloned') - .type(textInput) - .type('{enter}'); - - cy.get('.choices') - .first() - .find('.choices__list .choices__item') - .last() - .should($el => { - expect($el).to.contain(textInput); - }); - }); - - describe('inputting data', () => { - it('shows a dropdown prompt', () => { - cy.get('.choices') - .first() - .find('.choices__input--cloned') - .type(textInput); - - cy.get('.choices') - .first() - .find('.choices__list--dropdown') - .should('be.visible') - .should($dropdown => { - const dropdownText = $dropdown.text().trim(); - expect(dropdownText).to.equal( - `Press Enter to add "${textInput}"`, - ); - }); - }); - }); - - describe('input limit', () => { - beforeEach(() => { - for (let index = 0; index < 6; index++) { - cy.get('.choices') - .first() - .find('.choices__input--cloned') - .type(`${textInput} + ${index}`) - .type('{enter}'); - } - }); - - it('does not let me input more than 5 choices', () => { - cy.get('.choices') - .first() - .find('.choices__list--multiple') - .first() - .children() - .should($items => { - expect($items.length).to.equal(5); - }); - }); - - it('hides dropdown prompt once limit has been reached', () => { - cy.get('.choices') - .first() - .find('.choices__list--dropdown') - .should('not.be.visible'); - }); - }); - - describe('unique values', () => { - beforeEach(() => { - cy.get('.choices') - .eq(1) // second choices instance - .find('.choices__input--cloned') - .type(`${textInput}`) - .type('{enter}') - .type(`${textInput}`) - .type('{enter}'); - }); - - it('only allows me to input unique values', () => { - cy.get('.choices') - .eq(1) - .find('.choices__list--multiple') - .first() - .children() - .should($items => { - expect($items.length).to.equal(1); - }); - }); - - describe('inputting a non-unique value', () => { - it('displays dropdown prompt', () => { - cy.get('.choices') - .eq(1) - .find('.choices__list--dropdown') - .should('be.visible') - .should($dropdown => { - const dropdownText = $dropdown.text().trim(); - expect(dropdownText).to.equal( - 'Only unique values can be added.', - ); - }); - }); - }); - }); - }); - - describe('removing choices', () => { - beforeEach(() => { - cy.get('.choices') - .first() // second choices instance - .find('.choices__input--cloned') - .type(`${textInput}`) - .type('{enter}') - .type(`${textInput}`) - .type('{enter}'); - }); - - it('allows me to remove inputted choices', () => { - cy.get('.choices') - .first() - .find('.choices__list--multiple') - .first() - .children() - .should($items => { - expect($items.length).to.equal(2); - }); - - cy.get('.choices') - .first() - .find('.choices__list--multiple .choices__item') - .last() - .find('.choices__button') - .focus() - .click(); - - cy.get('.choices') - .first() - .find('.choices__list--multiple') - .first() - .should($items => { - expect($items.length).to.equal(1); - }); - }); - }); - }); - - describe('choices disabled', () => { - it('does not allow me to input data', () => { - cy.get('.choices') - .eq(3) - .find('.choices__input--cloned') - .should('be.disabled'); - }); - }); - }); - - describe('select-one element', () => {}); - - describe('select-multiple element', () => {}); -}); diff --git a/cypress/integration/text_element_spec.js b/cypress/integration/text_element_spec.js new file mode 100644 index 0000000..cb5a490 --- /dev/null +++ b/cypress/integration/text_element_spec.js @@ -0,0 +1,213 @@ +describe('Choices - text element', () => { + beforeEach(() => { + cy.visit('/text.html'); + }); + + describe('configs', () => { + const textInput = 'testing'; + + describe('basic', () => { + describe('adding choices', () => { + it('allows me to input choices', () => { + cy.get('[data-test-hook=basic]') + .find('.choices__input--cloned') + .type(textInput) + .type('{enter}'); + + cy.get('[data-test-hook=basic]') + .find('.choices__list--multiple .choices__item') + .last() + .should($el => { + expect($el).to.contain(textInput); + }); + }); + + it('updates the value of the original input', () => { + cy.get('[data-test-hook=basic]') + .find('.choices__input--cloned') + .type(textInput) + .type('{enter}'); + + cy.get('[data-test-hook=basic]') + .find('.choices__input.is-hidden') + .should('have.value', textInput); + }); + + describe('inputting data', () => { + it('shows a dropdown prompt', () => { + cy.get('[data-test-hook=basic]') + .find('.choices__input--cloned') + .type(textInput); + + cy.get('[data-test-hook=basic]') + .find('.choices__list--dropdown') + .should('be.visible') + .should($dropdown => { + const dropdownText = $dropdown.text().trim(); + expect(dropdownText).to.equal( + `Press Enter to add "${textInput}"`, + ); + }); + }); + }); + }); + + describe('removing choices', () => { + beforeEach(() => { + cy.get('[data-test-hook=basic]') + .find('.choices__input--cloned') + .type(`${textInput}`) + .type('{enter}') + .type(`${textInput}`) + .type('{enter}'); + }); + + it('allows me to remove inputted choices', () => { + cy.get('[data-test-hook=basic]') + .find('.choices__list--multiple') + .children() + .should($items => { + expect($items.length).to.equal(2); + }); + + cy.get('[data-test-hook=basic]') + .find('.choices__list--multiple .choices__item') + .last() + .find('.choices__button') + .focus() + .click(); + + cy.get('[data-test-hook=basic]') + .find('.choices__list--multiple') + .first() + .should($items => { + expect($items.length).to.equal(1); + }); + }); + }); + }); + + describe('unique values only', () => { + describe('unique values', () => { + beforeEach(() => { + cy.get('[data-test-hook=unique-values]') + .find('.choices__input--cloned') + .type(`${textInput}`) + .type('{enter}') + .type(`${textInput}`) + .type('{enter}'); + }); + + it('only allows me to input unique values', () => { + cy.get('[data-test-hook=unique-values]') + .find('.choices__list--multiple') + .first() + .children() + .should($items => { + expect($items.length).to.equal(1); + }); + }); + + describe('inputting a non-unique value', () => { + it('displays dropdown prompt', () => { + cy.get('[data-test-hook=unique-values]') + .find('.choices__list--dropdown') + .should('be.visible') + .should($dropdown => { + const dropdownText = $dropdown.text().trim(); + expect(dropdownText).to.equal( + 'Only unique values can be added.', + ); + }); + }); + }); + }); + }); + + describe('input limit', () => { + beforeEach(() => { + for (let index = 0; index < 6; index++) { + cy.get('[data-test-hook=input-limit]') + .find('.choices__input--cloned') + .type(`${textInput} + ${index}`) + .type('{enter}'); + } + }); + + it('does not let me input more than 5 choices', () => { + cy.get('[data-test-hook=input-limit]') + .find('.choices__list--multiple') + .first() + .children() + .should($items => { + expect($items.length).to.equal(5); + }); + }); + + it('hides dropdown prompt once limit has been reached', () => { + cy.get('[data-test-hook=input-limit]') + .find('.choices__list--dropdown') + .should('not.be.visible'); + }); + }); + + describe('regex filter', () => { + describe('a valid that satisfies regex', () => { + const input = 'joe@bloggs.com'; + + it('allows me to add choice', () => { + cy.get('[data-test-hook=regex-filter]') + .find('.choices__input--cloned') + .type(input) + .type('{enter}'); + + cy.get('[data-test-hook=regex-filter]') + .find('.choices__list .choices__item') + .last() + .should($choice => { + expect($choice).to.contain(input); + }); + }); + }); + + describe('inputting a value that does not satisfy the regex', () => { + it('displays dropdown prompt', () => { + cy.get('[data-test-hook=regex-filter]') + .find('.choices__input--cloned') + .type(`this is not an email address`) + .type('{enter}'); + + cy.get('[data-test-hook=regex-filter]') + .find('.choices__list--dropdown') + .should('not.be.visible'); + }); + }); + }); + + describe('prepend/append', () => { + beforeEach(() => { + cy.get('[data-test-hook=prepend-append]') + .find('.choices__input--cloned') + .type(textInput) + .type('{enter}'); + }); + + it('prepends and appends value to inputted value', () => { + cy.get('[data-test-hook=prepend-append]') + .find('.choices__list--multiple .choices__item') + .last() + .should($choice => { + expect($choice.data('value')).to.equal(`before-${textInput}-after`); + }); + }); + }); + + describe('disabled', () => { + it('does not allow me to input data', () => { + cy.get('[data-test-hook=disabled]') + .find('.choices__input--cloned') + .should('be.disabled'); + }); + }); + }); +}); diff --git a/package.json b/package.json index 7955983..0e29136 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./public/assets/scripts/choices.min.js", "types": "./types/index.d.ts", "scripts": { - "start": "NODE_ENV=development node server.js", + "start": "run-p js:watch css:watch", "build": "npm run js:build && npm run css:build", "lint": "eslint assets/**/*.js", "coverage": "nyc npm run test", @@ -14,6 +14,8 @@ "test:unit": "mocha --require ./config/test.js --compilers js:babel-core/register \"./src/**/**/**/**/*.test.js\" --exit", "test:unit:watch": "npm run test -- --watch --inspect=5556", "test:e2e": "run-p --race start cypress:run", + "test": "run-p test:unit test:e2e", + "js:watch": "NODE_ENV=development node server.js", "js:build:minimised": "webpack --env.minimize --config webpack.config.prod.js", "js:build:unminimised": "webpack --config webpack.config.prod.js", "js:build": "run-p js:build:minimised js:build:unminimised", @@ -67,7 +69,7 @@ "husky": "^0.14.3", "jsdom": "^11.5.1", "mocha": "^3.4.2", - "node-sass": "^3.4.2", + "node-sass": "^4.9.3", "nodemon": "^1.9.1", "npm-run-all": "^4.1.3", "nyc": "^11.0.3", diff --git a/public/assets/styles/base.css b/public/assets/styles/base.css index ade27d9..53522bb 100644 --- a/public/assets/styles/base.css +++ b/public/assets/styles/base.css @@ -172,4 +172,8 @@ h6, display: none; } +[data-test-hook] { + margin-bottom: 24px; +} + /*===== End of Section comment block ======*/ diff --git a/public/assets/styles/base.min.css b/public/assets/styles/base.min.css index 295b630..edf33ff 100644 --- a/public/assets/styles/base.min.css +++ b/public/assets/styles/base.min.css @@ -1 +1 @@ -*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label{margin-bottom:8px;font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo__img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}.is-hidden{display:none} \ No newline at end of file +*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label{margin-bottom:8px;font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo__img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}.is-hidden{display:none}[data-test-hook]{margin-bottom:24px} \ No newline at end of file diff --git a/public/test.html b/public/test.html deleted file mode 100644 index c8fbdb6..0000000 --- a/public/test.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - Choices - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -

Text inputs

- - - - - - - - - - - - - - - -
- -

Multiple select input

- -
- -

Single select input

- -
-
- - - - - - - - - diff --git a/public/test/text.html b/public/test/text.html new file mode 100644 index 0000000..1b4c189 --- /dev/null +++ b/public/test/text.html @@ -0,0 +1,128 @@ + + + + + + + Choices + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +

Text inputs

+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +

Multiple select input

+ +
+ +

Single select input

+ +
+
+ + + + + + + + + diff --git a/src/styles/base.scss b/src/styles/base.scss index 16f99a1..7b7b741 100644 --- a/src/styles/base.scss +++ b/src/styles/base.scss @@ -176,4 +176,8 @@ h6, display: none; } +[data-test-hook] { + margin-bottom: $global-guttering; +} + /*===== End of Section comment block ======*/ \ No newline at end of file