Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: _i18next2.default.use is not a function #1017

Closed
PerpetualWar opened this issue Feb 13, 2018 · 25 comments
Closed

TypeError: _i18next2.default.use is not a function #1017

PerpetualWar opened this issue Feb 13, 2018 · 25 comments

Comments

@PerpetualWar
Copy link

Hello,

I'm trying to setup testing suite with jest+ vue-test-utils or karma+jasmine+vue-test-utils (both throw same errors).

Is this problem with library or not ? Any idea how this can be solved ?

 TypeError: _i18next2.default.use is not a function

      34 |
      35 | i18next
    > 36 |      .use(Locize)
      37 |      .init(i18nextOptions);
      38 |
      39 | export default new VueI18Next(i18next);

      at Object.<anonymous> (src/app/locale/i18n.js:36:1)
      at Object.<anonymous> (src/app/store/modules/account/mutations.js:6:13)
      at Object.<anonymous> (src/app/store/modules/account/index.js:7:18)
      at Object.<anonymous> (src/app/store/index.js:17:16)      at src/app/pages/home/index/index.vue:24:14
      at Object.<anonymous> (src/app/pages/home/index/index.vue:230:3)
      at Object.<anonymous> (test/unit/home.spec.js:10:14)
@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

do you have this only in the test suite or in general (running website)

@PerpetualWar
Copy link
Author

only in test suite when I try to mock i18next.... without mock it says i18next is not defined.

Any help is appreciated.

@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

looks like the import does not be compatible with webpack

try import { default as i18next } from 'i18next';

@PerpetualWar
Copy link
Author

PerpetualWar commented Feb 13, 2018

where exactly ? if you mean in test, how do I initialize it, like this:

describe('Home Component', () => {

  const localVue = createLocalVue();
  localVue.use(i18next);
  
  let cmp;

  beforeEach(() => {
    cmp = shallow(Home, {
      i18next
    });
  });

  it('something', () => {
    console.log('bleh');
    // expect(cmp.vm).toBe(true);
  });

of you meant something else ?

@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

somewhere you require or import i18next -> depending on your bundler it will not correctly do

import i18next from 'i18next' -> as it won't work with default export correctly...typescript compiler and friends

so you might exchange that with a named import

@PerpetualWar
Copy link
Author

PerpetualWar commented Feb 13, 2018

ok, I only import it directly in locale file, and I setup options there.

I switched it:

// import i18next from 'i18next';
import { default as i18next } from 'i18next';
import VueI18Next from '@panter/vue-i18next';

still same error. Any other idea ?

@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

not really...just do a console.log of i18next...seems to be import related...

// import i18next from 'i18next';
import { default as i18next } from 'i18next';
console.log(i18next); // -> must be undefined i guess
import VueI18Next from '@panter/vue-i18next';

not had such an issue ever...hard to help without having options to debug...but must be related to import.

@PerpetualWar
Copy link
Author

i18next
	.use(Locize)
	.init(i18nextOptions);

export default new VueI18Next(i18next);

Can I somehow mock this i18next.use(Locize), would it work like that ?

Like I said , I only need to fix this in tests.

@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

for react -> but might help anyway: https://react.i18next.com/misc/testing.html

@jamuhl
Copy link
Member

jamuhl commented Feb 13, 2018

you can mock away i18next completely i think -> just provide a function t on it returning first prop and noops for the rest

const i18next = {
  use: () => {},
  init: () => {},
  t: key => key
}

@PerpetualWar
Copy link
Author

Thanks will try that out. ;)

@PerpetualWar
Copy link
Author

PerpetualWar commented Feb 14, 2018

ok, when I mock it like this:

import { shallow, mount, createLocalVue } from '@vue/test-utils';
// import i18n from './__mocks__/i18nextMock';
import Home from '../../src/app/pages/home/index/index.vue';

jest.mock('i18next', () => ({
  use: jest.fn(() => ({})),
  init: jest.fn(() => ({})),
  t: k => k
}));

describe('Home Component', () => {

  let cmp;

  beforeEach(() => {
    cmp = shallow(Home);
  });

  it('something', () => {
    console.log('bleh');
    expect(2+2).toBe(4);
    // expect(cmp.vm).toBeTruthy();
  });

});

it throws similar but different error:


    TypeError: _i18next2.default.use(...).init is not a function

      36 | i18next
      37 |      .use(Locize)
    > 38 |      .init(i18nextOptions);
      39 |
      40 | export default new VueI18Next(i18next);
      41 |

      at Object.<anonymous> (src/app/locale/i18n.js:38:1)
      at Object.<anonymous> (src/app/store/modules/account/mutations.js:6:13)
      at Object.<anonymous> (src/app/store/modules/account/index.js:7:18)
      at Object.<anonymous> (src/app/store/index.js:17:16)
      at src/app/pages/home/index/index.vue:24:14
      at Object.<anonymous> (src/app/pages/home/index/index.vue:230:3)
      at Object.<anonymous> (test/unit/home.spec.js:16:96)

now it complains of init not being a function.... even though both use and init are mocked.

Any suggestion would else could I try in this mock ?

@jamuhl
Copy link
Member

jamuhl commented Feb 14, 2018

you will need to return this from your use function:

const i18next = {
  use: () => { return this; },
  init: () => {},
  t: key => key
}

@PerpetualWar
Copy link
Author

if I set :

jest.mock('i18next', () => ({
  use: () => { return this; },
  init: () => { },
  t: k => k
}));

it says: TypeError: Cannot read property 'init' of undefined

The same error if I remove return this , just the same (when it's empty function).

@jamuhl
Copy link
Member

jamuhl commented Feb 14, 2018

then try returning the constant itself return i18next

@jamuhl
Copy link
Member

jamuhl commented Feb 14, 2018

in the end just make the function chain work ;)

@PerpetualWar
Copy link
Author

PerpetualWar commented Feb 14, 2018

jest.mock('i18next', () => ({
  use: () => {
    return {
      init: () => { }
    };
  },
  t: k => k
}));

This partially worked to get another error msg:

TypeError: this.i18next.on is not a function

      38 |      .init(i18nextOptions);
      39 |
    > 40 | export default new VueI18Next(i18next);
      41 |

https://stackoverflow.com/questions/48789110/how-to-mock-i18next-module-in-jest

@jamuhl
Copy link
Member

jamuhl commented Feb 14, 2018

seems the vue-i18next depends on the event emitter build in...you will have to mock that too

evetual a good idea to ask there @panter/vue-i18next what functions on i18next are needed to have a complete mock

@jamuhl
Copy link
Member

jamuhl commented Feb 19, 2018

closing for now...feel free to reopen if still some issue

@jamuhl jamuhl closed this as completed Feb 19, 2018
@instinctcoder
Copy link

instinctcoder commented Apr 26, 2019

i have same issue. but i'm using typescript and reactjs

i follow the last setup from above comment, could you please advise? Thanks.


jest.mock('i18next', () => ({
    use: () => {
      return {
        init: () => { }
      };
    },
    t: k => k
  }));

give me this error


    TypeError: Cannot read property 'init' of undefined

       6 |  
       7 |  i18next
    >  8 |   .init({
         |    ^
       9 |     interpolation: {
      10 |       escapeValue: false,
      11 |     },

@PerminovEugene
Copy link

Something wrong with imports in module. I've changed my code to
const i18n = require('i18next').default; and this works fine

@jamuhl
Copy link
Member

jamuhl commented Oct 18, 2019

Nothing wrong with imports...depends on the environment picking commonjs or es6 module...

@lukehutton-clearly
Copy link

lukehutton-clearly commented Jun 1, 2020

Thanks for comments, I got it working with:

import i18next from "i18next";

jest.mock("i18next", () => ({
  use: () => i18next,
  init: jest.fn()
}));

@ghost
Copy link

ghost commented Aug 25, 2020

I'm also getting same error : _i18next.default.addResourceBundle is not a function

Although, My error was resolved via adding this two changes.

  1. create mocks folder in your /src directory
  2. then create new flle named "react-i18next.js"
  3. then simply pase the code as instructed here : https://github.com/i18next/react-i18next/blob/master/example/v9.x.x/test-jest/__mocks__/react-i18next.js
  4. then go into your */.test.js file
  5. then add mock function like below
    jest.mock("i18next", () => ({ addResourceBundle: jest.fn(), }));

And woooo.. It works!!

@sohailupu
Copy link

i am also getting same issue
i tried above solutions as well but unfortunately none of them worked for me

TypeError: _i18next.default.use is not a function

  13 |
  14 | i18n
> 15 |   .use(languageDetector)
     |    ^
  16 |   .use(initReactI18next)
  17 |   .init({
  18 |     fallbackLng: "en",

//mocking
jest.mock('i18next', () => ({ use: () => { return { init: () => { }, }; }, t: key => key, }));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants