diff --git a/.all-contributorsrc b/.all-contributorsrc index 70112b1..5e98bc5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -62,6 +62,16 @@ "code", "test" ] + }, + { + "login": "42tte", + "name": "Kristoffer NordstrΓΆm", + "avatar_url": "https://avatars0.githubusercontent.com/u/8436510?v=4", + "profile": "https://github.com/42tte", + "contributions": [ + "code", + "test" + ] } ] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1eeb86..ceeb658 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,3 +56,4 @@ Also, please watch the repo and respond to questions/bug reports/feature requests! Thanks! [issues]: https://github.com/educents/vue-autosuggest/issues +[all-contributors]: https://github.com/kentcdodds/all-contributors diff --git a/README.md b/README.md index 66f575f..2b65146 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![MIT License][license-badge]][LICENSE] [![gzip size][size-badge]](https://unpkg.com/vue-autosuggest@latest) -[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] @@ -445,8 +445,8 @@ For IE11 and below, some functionality may not work. For example, you will have Thanks goes to these people ([emoji key][emojis]): -| [
Darren Jennings](https://darrenjennings.github.io)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Code") [πŸ“–](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Documentation") [πŸš‡](#infra-darrenjennings "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Tests") [🎨](#design-darrenjennings "Design") [πŸ’‘](#example-darrenjennings "Examples") | [
Evgeniy Kulish](https://github.com/ekulish)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=ekulish "Code") [🎨](#design-ekulish "Design") [πŸ’‘](#example-ekulish "Examples") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=ekulish "Tests") | [
Scott Smith](https://github.com/scottadamsmith)
[πŸ›](https://github.com/darrenjennings/vue-autosuggest/issues?q=author%3Ascottadamsmith "Bug reports") [πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=scottadamsmith "Code") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=scottadamsmith "Tests") | [
Fernando Machuca](https://github.com/chuca)
[🎨](#design-chuca "Design") | [
BerniML](https://github.com/BerniML)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=BerniML "Code") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=BerniML "Tests") | -| :---: | :---: | :---: | :---: | :---: | +| [
Darren Jennings](https://darrenjennings.github.io)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Code") [πŸ“–](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Documentation") [πŸš‡](#infra-darrenjennings "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=darrenjennings "Tests") [🎨](#design-darrenjennings "Design") [πŸ’‘](#example-darrenjennings "Examples") | [
Evgeniy Kulish](https://github.com/ekulish)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=ekulish "Code") [🎨](#design-ekulish "Design") [πŸ’‘](#example-ekulish "Examples") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=ekulish "Tests") | [
Scott Smith](https://github.com/scottadamsmith)
[πŸ›](https://github.com/darrenjennings/vue-autosuggest/issues?q=author%3Ascottadamsmith "Bug reports") [πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=scottadamsmith "Code") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=scottadamsmith "Tests") | [
Fernando Machuca](https://github.com/chuca)
[🎨](#design-chuca "Design") | [
BerniML](https://github.com/BerniML)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=BerniML "Code") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=BerniML "Tests") | [
Kristoffer NordstrΓΆm](https://github.com/42tte)
[πŸ’»](https://github.com/darrenjennings/vue-autosuggest/commits?author=42tte "Code") [⚠️](https://github.com/darrenjennings/vue-autosuggest/commits?author=42tte "Tests") | +| :---: | :---: | :---: | :---: | :---: | :---: | Thanks to [@chuca](https://github.com/chuca) for the logo design. diff --git a/__tests__/__snapshots__/autosuggest.test.js.snap b/__tests__/__snapshots__/autosuggest.test.js.snap index 7eb2076..c1a778a 100644 --- a/__tests__/__snapshots__/autosuggest.test.js.snap +++ b/__tests__/__snapshots__/autosuggest.test.js.snap @@ -1,7 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Autosuggest @click and @selected listener events works as expected 1`] = ` -
+
+
@@ -9,7 +10,8 @@ exports[`Autosuggest @click and @selected listener events works as expected 1`] `; exports[`Autosuggest can click outside document to trigger close 1`] = ` -
+
+
@@ -17,7 +19,8 @@ exports[`Autosuggest can click outside document to trigger close 1`] = ` `; exports[`Autosuggest can customize css prefix 1`] = ` -
+
+
    @@ -81,7 +84,8 @@ exports[`Autosuggest can customize css prefix 1`] = ` `; exports[`Autosuggest can customize ids and classes for container divs 1`] = ` -
    +
    +
      @@ -145,7 +149,8 @@ exports[`Autosuggest can customize ids and classes for container divs 1`] = ` `; exports[`Autosuggest can display section header 1`] = ` -
      +
      +
        @@ -172,7 +177,8 @@ exports[`Autosuggest can display section header 1`] = ` `; exports[`Autosuggest can display ul and li classNames 1`] = ` -
        +
        +
          @@ -236,7 +242,8 @@ exports[`Autosuggest can display ul and li classNames 1`] = ` `; exports[`Autosuggest can handle null data 1`] = ` -
          +
          +
          @@ -244,7 +251,8 @@ exports[`Autosuggest can handle null data 1`] = ` `; exports[`Autosuggest can modify input type attribute 1`] = ` -
          +
          +
          @@ -252,7 +260,8 @@ exports[`Autosuggest can modify input type attribute 1`] = ` `; exports[`Autosuggest can mount 1`] = ` -
          +
          +
          @@ -260,7 +269,8 @@ exports[`Autosuggest can mount 1`] = ` `; exports[`Autosuggest can render default suggestion value by property name 1`] = ` -
          +
          +
          @@ -268,7 +278,8 @@ exports[`Autosuggest can render default suggestion value by property name 1`] = `; exports[`Autosuggest can render section slots 1`] = ` -
          +
          +
            @@ -337,7 +348,8 @@ exports[`Autosuggest can render section slots 1`] = ` `; exports[`Autosuggest can render simplest component with single onSelected 1`] = ` -
            +
            +
              @@ -408,7 +420,8 @@ exports[`Autosuggest can render simplest component with single onSelected 1`] = `; exports[`Autosuggest can render slots 1`] = ` -
              +
              +
              @@ -436,7 +449,8 @@ exports[`Autosuggest can render slots 1`] = ` `; exports[`Autosuggest can render suggestions 1`] = ` -
              +
              +
                @@ -462,7 +476,8 @@ exports[`Autosuggest can render suggestions 1`] = ` `; exports[`Autosuggest can select from suggestions using keystroke 1`] = ` -
                +
                +
                @@ -470,7 +485,8 @@ exports[`Autosuggest can select from suggestions using keystroke 1`] = ` `; exports[`Autosuggest can use escape key to exit 1`] = ` -
                +
                +
                @@ -478,7 +494,8 @@ exports[`Autosuggest can use escape key to exit 1`] = ` `; exports[`Autosuggest highlights first option on keydown when previously closed 1`] = ` -
                +
                +
                  @@ -542,7 +559,8 @@ exports[`Autosuggest highlights first option on keydown when previously closed 1 `; exports[`Autosuggest is aria complete 1`] = ` -
                  +
                  +
                    diff --git a/__tests__/autosuggest.test.js b/__tests__/autosuggest.test.js index 51ab401..074c3a4 100644 --- a/__tests__/autosuggest.test.js +++ b/__tests__/autosuggest.test.js @@ -216,7 +216,7 @@ describe("Autosuggest", () => { } } const wrapper = mount(multipleAutosuggest, { - attachToDocument: true + attachToDocument: true }); const autosuggestInstances = wrapper.findAll(Autosuggest); @@ -228,7 +228,7 @@ describe("Autosuggest", () => { input1.trigger("click"); input2.trigger("click"); - + expect(autosuggest1.findAll("li.autosuggest__results-item").length).toBe(5); expect(autosuggest1.findAll("li.autosuggest__results-item").length).toBe(5); @@ -262,7 +262,7 @@ describe("Autosuggest", () => { input.setValue("G"); window.document.dispatchEvent(new Event("mousedown")); window.document.dispatchEvent(new Event("mouseup")); - + await wrapper.vm.$nextTick(() => {}); const renderer = createRenderer(); @@ -319,23 +319,29 @@ describe("Autosuggest", () => { } const wrapper = mount(Autosuggest, { propsData }); - const input = wrapper.find("input"); - expect(input.attributes()["role"]).toBe("combobox"); + const combobox = wrapper.find("[role='combobox']"); + expect(combobox.exists()).toBeTruthy(); + expect(combobox.attributes()["aria-haspopup"]).toBe("listbox"); + expect(combobox.attributes()["aria-owns"]).toBe("autosuggest-autosuggest__results"); + + const input = combobox.find("input"); expect(input.attributes()["aria-autocomplete"]).toBe("list"); expect(input.attributes()["aria-activedescendant"]).toBe(""); - expect(input.attributes()["aria-owns"]).toBe("autosuggest-autosuggest__results"); - + expect(input.attributes()["aria-controls"]).toBe("autosuggest-autosuggest__results"); + // aria owns needs to be an "id", #191 - const results = wrapper.find(`#${input.attributes()["aria-owns"]}`) + let results = wrapper.find(`#${combobox.attributes()["aria-owns"]}`) + expect(results.exists()).toBeTruthy() + results = wrapper.find(`#${input.attributes()["aria-controls"]}`) expect(results.exists()).toBeTruthy() - + // TODO: Make sure aria-completeness is actually 2legit2quit. input.trigger("click"); input.setValue("G"); - expect(input.attributes()["aria-haspopup"]).toBe("true"); - + expect(combobox.attributes()["aria-expanded"]).toBe("true"); + // make sure aria-labeledby references the section config label, and that it's an "id" const ul = wrapper.find('ul') expect(ul.attributes()['aria-labelledby']).toBe('autosuggest-Suggestions') @@ -457,7 +463,7 @@ describe("Autosuggest", () => { it("search input prop type handles string and integers only", async () => { let props = { - ...defaultProps, + ...defaultProps, inputProps: {...defaultProps.inputProps} }; @@ -493,7 +499,7 @@ describe("Autosuggest", () => { wrapper.setData({ searchInput: () => { /* BAD */ } }); await wrapper.vm.$nextTick(() => {}); input.trigger("blur"); - + // Should throw validation error expect(mockConsole).toHaveBeenCalled(); }); @@ -516,7 +522,7 @@ describe("Autosuggest", () => { const input = wrapper.find("input"); input.trigger("click"); input.setValue("G"); - + expect(wrapper.findAll('.header-dude').length).toEqual(1); expect(wrapper.findAll('#footer-dude span').length).toEqual(2); expect(wrapper.findAll('h1').length).toEqual(5); @@ -531,7 +537,7 @@ describe("Autosuggest", () => { expect(str).toMatchSnapshot(); }); }); - + it("can render section slots", async () => { const props = { ...defaultProps }; props.suggestions.push({ name: 'dogs', data: ['spike', 'bud', 'rover']}) @@ -587,7 +593,7 @@ describe("Autosuggest", () => { }, attachToDocument: true }); - + const input = wrapper.find("input"); input.trigger("click"); input.setValue("G"); @@ -605,7 +611,7 @@ describe("Autosuggest", () => { expect(str).toMatchSnapshot(); }); }); - + it("can customize css prefix", async () => { const wrapper = mount(Autosuggest, { propsData: { @@ -622,7 +628,7 @@ describe("Autosuggest", () => { }, attachToDocument: true }); - + const input = wrapper.find("input"); input.trigger("click"); input.setValue("G"); @@ -632,7 +638,7 @@ describe("Autosuggest", () => { expect(wrapper.find('#the-input-thing').is('input')).toBe(true); expect(wrapper.find('.the-results-container').is('div')).toBe(true); expect(wrapper.find('.the-results').is('div')).toBe(true); - + // Prefix checks expect(wrapper.find('#v__results-item--0').is('li')).toBeTruthy() expect(wrapper.find('.v__results-item').is('li')).toBeTruthy() @@ -737,7 +743,7 @@ describe("Autosuggest", () => { expect(str).toMatchSnapshot(); }); }); - + it("can modify input props", async () => { const Parent = { template: `
                    @@ -757,11 +763,11 @@ describe("Autosuggest", () => { const wrapper = mount(Parent); const input = wrapper.find('input[type="text"]') expect(input.attributes("placeholder")).toBe('Type here...'); - + wrapper.setData({ ph: 'Please type here...' }) expect(input.attributes("placeholder")).toBe('Please type here...') }); - + it("can handle null data", async () => { const props = {...defaultProps, suggestions: [{ data: null }]}; @@ -775,7 +781,7 @@ describe("Autosuggest", () => { expect(str).toMatchSnapshot(); }); }); - + it("highlights first option on keydown when previously closed", async () => { const props = { ...defaultProps }; props.inputProps = { ...defaultProps.inputProps }; @@ -795,7 +801,7 @@ describe("Autosuggest", () => { input.trigger("keydown.down"); expect(wrapper.findAll("li.autosuggest__results-item--highlighted")).toHaveLength(1) - + const item = wrapper.find("li.autosuggest__results-item--highlighted") expect(item.attributes('data-suggestion-index')).toBe('0') expect(input.attributes('aria-activedescendant')).toBe('autosuggest__results-item--0') @@ -808,7 +814,7 @@ describe("Autosuggest", () => { expect(str).toMatchSnapshot(); }); }); - + it("can display ul and li classNames", async () => { const props = { ...defaultProps }; props.sectionConfigs.default.liClass = { 'hello-li': true } @@ -825,13 +831,13 @@ describe("Autosuggest", () => { input.trigger("click"); input.setValue("G"); - + const ul = wrapper.find("ul") const li = ul.find("li:nth-child(1)") expect(ul.classes()).toContain('hello-ul'); expect(li.classes()).toContain('hello-li'); - + const renderer = createRenderer(); renderer.renderToString(wrapper.vm, (err, str) => { if (err) { @@ -860,7 +866,7 @@ describe("Autosuggest", () => { await wrapper.vm.$nextTick(() => {}) expect(wrapper.emitted().closed).toBeTruthy(); }); - + it("emits item-changed event", async () => { const props = { ...defaultProps }; props.inputProps = { ...defaultProps.inputProps }; @@ -868,7 +874,7 @@ describe("Autosuggest", () => { const wrapper = mount(Autosuggest, { propsData: props, }); - + const input = wrapper.find("input"); input.setValue("G"); input.trigger("keydown.down"); @@ -878,19 +884,19 @@ describe("Autosuggest", () => { expect(wrapper.emitted()['item-changed']).toHaveLength(2); const itemChanged1 = wrapper.emitted()['item-changed'][0] const itemChanged2 = wrapper.emitted()['item-changed'][1] - + // Emits with item and index expect(itemChanged1[0].item).toBe('clifford kits'); expect(itemChanged1[1]).toBe(0); expect(itemChanged2[0].item).toBe('friendly chemistry'); expect(itemChanged2[1]).toBe(1); - + input.trigger("keydown.up"); await wrapper.vm.$nextTick(() => {}) input.trigger("keydown.up"); await wrapper.vm.$nextTick(() => {}) await wrapper.vm.$nextTick(() => {}) - + // Ensure empty item-changed is emitted when user keys back // to the input #177 expect(wrapper.emitted()['item-changed']).toHaveLength(4) @@ -898,7 +904,7 @@ describe("Autosuggest", () => { expect(itemChangedEmpty[0]).toBeNull(); expect(itemChangedEmpty[1]).toBeNull(); }); - + it("current index resilient against many keyups #190", async () => { const props = { ...defaultProps }; props.inputProps = { ...defaultProps.inputProps }; @@ -906,7 +912,7 @@ describe("Autosuggest", () => { const wrapper = mount(Autosuggest, { propsData: props, }); - + const input = wrapper.find("input"); input.setValue("G"); input.trigger("keydown.down"); @@ -914,14 +920,14 @@ describe("Autosuggest", () => { expect(wrapper.vm.currentIndex).toBe(0) input.trigger("keydown.up"); expect(wrapper.vm.currentIndex).toBe(-1) - + // Go into the upside down, but make sure to come back unscathed await wrapper.vm.$nextTick(() => {}) input.trigger("keydown.up"); await wrapper.vm.$nextTick(() => {}) input.trigger("keydown.up"); await wrapper.vm.$nextTick(() => {}) - + expect(wrapper.vm.currentIndex).toBe(-1) }); }); diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..6e8349f --- /dev/null +++ b/codecov.yml @@ -0,0 +1,31 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + status: + project: + default: + threshold: 0.2 + if_not_found: success + patch: + default: + enabled: no + if_not_found: success + changes: + default: + enabled: no + if_not_found: success + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: false + diff --git a/src/Autosuggest.vue b/src/Autosuggest.vue index 59e9b5c..3ba0a24 100644 --- a/src/Autosuggest.vue +++ b/src/Autosuggest.vue @@ -1,26 +1,28 @@