Jest: рдЯреЗрд╕реНрдЯ рдЕрдЧрд░ рд╡рд╕реНрддреБ, рд╕рд░рдгреА рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧред

рдХреЛ рдирд┐рд░реНрдорд┐рдд 3 рдордИ 2017  ┬╖  29рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: facebook/jest

рдХреНрдпрд╛ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдХреЛрдИ рдШрдЯрдХ рдСрдмреНрдЬреЗрдХреНрдЯ, рд╕рд░рдгреА рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рдпрд╛ рдирд╣реАрдВ? рдпрд╣ рдЪрд╛рдп рдХреЗ 'рдЪрд╛рд╣рд┐рдП.рдмреА.рдП' рдХреЗ тАЛтАЛрд╕рдорд╛рди рд╣реЛрдЧрд╛ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЬреЛ рд▓реЛрдЧ рдЗрд╕реЗ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ toBeType рдПрдХреНрд╕рдЯреЗрдВрд╢рди

expect.extend({
    toBeType(received, argument) {
        const initialType = typeof received;
        const type = initialType === "object" ? Array.isArray(received) ? "array" : initialType : initialType;
        return type === argument ? {
            message: () => `expected ${received} to be type ${argument}`,
            pass: true
        } : {
            message: () => `expected ${received} to be type ${argument}`,
            pass: false
        };
    }
});

describe("testing extended expect", () => {
    it("tests normal types correctly", () => {
        expect("").toBeType("string");
        expect({}).toBeType("object");
        expect(1).toBeType("number");
    });
    it("tests array types correctly", () => {
        expect([]).toBeType("array");
    });
    it("works with promises", () => {
        expect(Promise.resolve([])).resolves.toBeType("array");
    });
});

рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрд░ рдЯреАрдмреАрдПрдЪ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдиреЛрдЯ - рдпрджрд┐ рдЖрдк рдЙрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЛ рдЕрдкрдиреА рд╕реЗрдЯрдЕрдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдбрд╛рд▓ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕реЗ setupTestFrameworkScriptFile рдирд╣реАрдВ setupFiles (рдЬреИрд╕рд╛ рдХрд┐ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗрд╡рд▓ рдкреВрд░реНрд╡ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ)

рд╕рднреА 29 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдирд╣реАрдВ, рд╡рд╣рд╛рдБ рдирд╣реАрдВ рд╣реИред рдЖрдкрдХреЛ рд╕рднреА рдЙрдкрд▓рдмреНрдз рдорд┐рд▓рд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдпрд╣рд╛рдВ рдорд┐рд▓реЗрдЧреА: https://facebook.github.io/jest/docs/en/expect.html

рдЖрдк рдЙрд╕рдХреЗ рд▓рд┐рдП lodash рдЬреИрд╕реЗ рд╕рд╛рджреЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдпрд╛ рд╕рд╣рд╛рдпрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

test('name', () => {
  // array
  expect(Array.isArray(['value'])).toBe(true);
  // string
  expect(typeof 'value').toBe('string');
  // object
  expect({value: 'value'}).toBeTruthy();
  expect(typeof {value: 'value'}).toBe('object');
})

рдорд╛рдореВрд▓реА рдмрд┐рдВрджреБ - рдпрд╣ рд╡рд╛рджреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдореЗрдВ рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

expect(somePromise).resolves.toBe(...) рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдЖрдк рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рддреЛ рдХреНрдпрд╛ рд╕рд╛рдордЧреНрд░реА рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рд╕рд┐рд░реНрдл рдЗрддрдирд╛ рд╣реИ рдХрд┐ред рдореБрдЭреЗ рдЙрдореНрдореАрдж рдереА рдХрд┐ expects.stringContaining("") рдПрдХ рдХрд╛рдо рд╣реЛ рдЬрд╛рдПрдЧрд╛ рд▓реЗрдХрд┐рди рд╡рд╣ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

@abritinthebay рдореИрдВ рдареАрдХ рдЙрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реВрдВ рдФрд░ Google рдореЗрдВ рдпрд╣ рдкрд╣рд▓рд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ, рд╢рд╛рдпрдж рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП?

рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕ рдкрд░ рдереЛрдбрд╝рд╛ рдФрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рдерд╛ рддрд╛рдХрд┐ typeof рднрд╛рдЧ рд╣реЛред рдЙрджрд╛рд╣рд░рдг:

expect(somePromise.then(data => typeof data)).resolves.toBe("object");

рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рд╕рд╛рдл рдирд╣реАрдВ рд╣реИред

@thymikee рдЪреАрдЬреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкрд░реНрдпрд╛рдкреНрдд рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ (рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ) рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдврд╛рдВрдЪреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдИ рдмрд╣рд╛рдирд╛ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЙрдирдХреА рдХрдореА рд╣реИред рдЖрдкрдХреЗ рд╡рд┐рдХрд▓реНрдк рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЙрд╕рдХреЗ рд╕рднреА рд╕рдВрджрд░реНрдн рдЦреЛ рджреЗрддреЗ рд╣реИрдВред

рдпрд╣ expect(Array.isArray(['value'])).toBe(false); рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ

expect(received).toBe(expected)
    Expected value to be (using ===):
      false
    Received:
      true. 

рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдпрд╛ рддреЛ рднрдпрд╛рдирдХ рдЕрднрд┐рдХрдерди рд╕рдВрджреЗрд╢ рдорд┐рд▓рддреЗ рд╣реИрдВ рдпрд╛ рд╣рдореЗрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдБрдЪреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЗрд╕реНрдЯ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдХреНрдпрд╛ рдпрд╣ рдЬреЗрд╕реНрдЯ рдХреЗ рдЕрдиреБрд░рдХреНрд╖рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╡рд┐рдкрд░реАрдд рдЬреЛ рдЗрди рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рд╕реНрд╡рдпрдВ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ?

рдлрд┐рд░ expect.extend рд╕рд╛рде рдЕрдкрдиреЗ рдЦреБрдж рдХреЗ рдореИрдЪрд░реНрд╕ рдмрдирд╛рдПрдВ рдФрд░ рдПрдХ npm рдореЙрдбреНрдпреВрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВред рдпрджрд┐ рдпрд╣ рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЕрдВрддрддрдГ рдЬреЗрд╕реНрдЯ рдХреЛрд░ рдореЗрдВ рд╡рд┐рд▓рдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ;)

рдЬреЛ рд▓реЛрдЧ рдЗрд╕реЗ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ toBeType рдПрдХреНрд╕рдЯреЗрдВрд╢рди

expect.extend({
    toBeType(received, argument) {
        const initialType = typeof received;
        const type = initialType === "object" ? Array.isArray(received) ? "array" : initialType : initialType;
        return type === argument ? {
            message: () => `expected ${received} to be type ${argument}`,
            pass: true
        } : {
            message: () => `expected ${received} to be type ${argument}`,
            pass: false
        };
    }
});

describe("testing extended expect", () => {
    it("tests normal types correctly", () => {
        expect("").toBeType("string");
        expect({}).toBeType("object");
        expect(1).toBeType("number");
    });
    it("tests array types correctly", () => {
        expect([]).toBeType("array");
    });
    it("works with promises", () => {
        expect(Promise.resolve([])).resolves.toBeType("array");
    });
});

рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрд░ рдЯреАрдмреАрдПрдЪ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдиреЛрдЯ - рдпрджрд┐ рдЖрдк рдЙрд╕ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЛ рдЕрдкрдиреА рд╕реЗрдЯрдЕрдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдбрд╛рд▓ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕реЗ setupTestFrameworkScriptFile рдирд╣реАрдВ setupFiles (рдЬреИрд╕рд╛ рдХрд┐ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗрд╡рд▓ рдкреВрд░реНрд╡ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ)

рдзрдиреНрдпрд╡рд╛рдж @abritinthebay

рддреЛ рдЕрдЧрд░ рд▓реЛрдЧ рдЗрд╕реЗ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдореИрдВрдиреЗ рдЗрд╕реЗ рдПрдирдкреАрдПрдо рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд▓рдкреЗрдЯ рд▓рд┐рдпрд╛:

https://www.npmjs.com/package/jest-tobetype

describe("assertion framework", ()=> {
 it("should check primitive types", () => {
   expect(expect.toBeA).toBeA("function")
  })
})

рд╡рд┐рдлрд▓: рдЙрдореНрдореАрдж (...)ред toBeA рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рд╣реИрд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: рдЙрдореНрдореАрдж (...)ред toBeA рдПрдХ рд╕рдорд╛рд░реЛрд╣ рдирд╣реАрдВ рд╣реИ

https://github.com/jest-community/jest-extended рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдореИрдЪрд░реНрд╕ рд╣реИрдВ рдЬреЛ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ)ред

рдореИрдВ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ toBeInstanceOf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ:

expect($wrapper.vm.countries).toBeInstanceOf(Array);

рдЙрдореНрдореАрдж рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рдЦреБрдж рдХреЗ рдореИрдЪрд░реНрд╕ рдмрдирд╛рдПрдВ рдФрд░ рдлрд┐рд░ рдПрдирдкреАрдПрдо рдореЙрдбреНрдпреВрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВред рдпрджрд┐ рдпрд╣ рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЕрдВрддрддрдГ рдЬреЗрд╕реНрдЯ рдХреЛрд░ рдореЗрдВ рд╡рд┐рд▓рдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ;)

рд╣рд╛рдБ, рдФрд░ рдЬрдм рдЖрдк рдЙрд╕ рдкрд░ рд╣реЛрдВ, рддрдм рдЖрдк рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдордЬрд╝рд╛рдХ рдврд╛рдВрдЪрд╛ рд▓рд┐рдЦ тАЛтАЛрд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рд╕рд┐рд░реНрдл GitHub рдкрд░ рдЖрдкрдХреЛ рдорд┐рд▓рдиреЗ рд╡рд╛рд▓реЗ рд╕рдмрд╕реЗ рдЦрд░рд╛рдм рдЙрддреНрддрд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рддреЛ @abritinthebay рдиреЗ рд╡рд╣реА рдХрд┐рдпрд╛ рдЬреЛ @thymikee рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ (рдЬреЛ рдорд╛рдирдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдерд╛)ред

рдЕрдм рдЬрдм рдЙрд╕ рдмрд╣рд╛рджреБрд░ рдЖрддреНрдорд╛ рдиреЗ рд╕рд╛рд░рд╛ рдХрд╛рдо рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ, рддреЛ рд╣рдордореЗрдВ рд╕реЗ рдмрд╛рдХреА рд▓реЛрдЧреЛрдВ рдХреЛ рдЖрдЦрд┐рд░рдХрд╛рд░ рдпрд╣ рдореИрдЪрд░ рдХрдм рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ (рдмрд┐рдирд╛ рджреВрд╕рд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдП)? рдХреНрдпрд╛ рдЕрдиреБрд░рдХреНрд╖рдХ рдЕрднреА рднреА рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдЬреЗрд╕реНрдЯ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдпрд╛ рдпрд╣ рд╕рд┐рд░реНрдл рдЙрдирдХреЗ рд░рдбрд╛рд░ рд╕реЗ рдЧрд┐рд░ рдЧрдпрд╛ рд╣реИ?

рд╣рдо рдЗрд╕реЗ рдХреЛрд░ рдореЗрдВ рдмрдирд╛рдиреЗ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рд╕рдЦреНрдд рд╣реИрдВ рдФрд░ рдЖрдо рддреМрд░ рдкрд░ рдЪреАрдиреА рдореИрдЪрд░реНрд╕ рдирд╣реАрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЬреЗрд╕реНрдЯ рдХреЛрд░ рдПрдХ рдХрд╛рдлреА рдмрдбрд╝рд╛ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рд╣реИ рдФрд░ рд╣рдо рдЬреЛ рднреА рдореИрдЪрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рд╡рд╣ рд░рдЦрд░рдЦрд╛рд╡ рд▓рд╛рдЧрдд рдХреЛ рдмрдврд╝рд╛рддрд╛ рд╣реИ

рдЪреАрдиреА рдХреЗ рд▓рд┐рдП, рд╣рдо рдЖрдо рддреМрд░ рдкрд░ https://github.com/jest-community/jest-extended . рдХреА рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВ

рдПрдХ рдЖрджрдореА рдХреА рдЪреАрдиреА рджреВрд╕рд░реЗ рдЖрджрдореА рдХреА (рдпрд╛ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХрдо рд╕реЗ рдХрдо рд╕рд╛рдд рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреА) рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рдФрд░ рддрд╛рд░реНрдХрд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ рдЬреЛ рдореВрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рд╣реИред

рдЬрд╛рд╣рд┐рд░ рд╣реИ рдПрдХ рдЕрдиреБрд░рдХреНрд╖рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдкрдХрд╛ рд╡реЛрдЯ рд╣рдо рд╕рднреА рдХреЛ рдкрдЫрд╛рдбрд╝ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рд╣рд░ рддрд░рд╣ рдХреА рдЪрд┐рдВрддрд╛рдПрдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕рдХрд╛ рдкреВрд░рд╛ рд╕рдореНрдорд╛рди рдХрд░рддрд╛ рд╣реВрдВред рд▓реЗрдХрд┐рди рдореИрдВ рдмрд╕ рдЗрддрдирд╛ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдЖрдк рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣рд╛рдВ рд╣рд░ рдХреЛрдИ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдореБрдЦреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдХреНрдпреЛрдВ рдорд╛рдирддрд╛ рд╣реИ (рдЗрддрдиреА рджреГрдврд╝рддрд╛ рд╕реЗ рдХрд┐ рдПрдХ рд╡реНрдпрдХреНрддрд┐ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рд╣реБрдкреНрд╕ рд╕реЗ рдХреВрдж рдЧрдпрд╛)ред рдпрд╣рд╛рдВ рдПрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдЬреЗрд╕реНрдЯ рдХреЛрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рддреЗ рд╣реИрдВ (рдФрд░ рдИрдорд╛рдирджрд╛рд░ рд░рд╣реЗрдВ, рддреЛ рдЙрдирдореЗрдВ рд╕реЗ 9 0% рдЬреЗрд╕реНрдЯ-рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрднреА рднреА рдирд╣реАрдВ рд╕реБрдиреЗрдВрдЧреЗ) рдЦреЛ рджреЗрдВрдЧреЗред

.to.be.an.instanceOf рдпрд╣ рдирд╣реАрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рд╣реИ рдХрд┐ рдХрд┐рддрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЛрдЪрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЙрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рднрд▓реЗ рд╣реА рдЖрдк рдЗрд╕реЗ рдЪреАрдиреА рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЖрдк рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдмрд┐рдирд╛ рдЬреЗрд╕реНрдЯ рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╕реЗ рд╡рдВрдЪрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рд╣рд╛рдБ рдореИрдВ рд╕реБрдирддрд╛ рд╣реВрдБред рд╕реНрдкрд╖реНрдЯ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, "рдЪреАрдиреА" рд╕реЗ рдореЗрд░рд╛ рдорддрд▓рдм рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рд╣реИ рдЬреЛ рдЪреАрдЬреЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдпрд╛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рдЪреАрдиреА, рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдПрдХ рдРрд╕реА рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рд░реВрдкрд╛рдВрддрд░ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИ

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реИ:

// Supported
expect(typeof foo).toBe('string');

// Proposed Sugar
expect(foo).toBeType('string');

рддреЛ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдо рдЬрд╛рдБрдЪ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдХрд░ред рд╣рдо рдкрд╣рд▓реЗ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╡рд┐рдХрд▓реНрдк рдХреЛрд░ toBe рдореИрдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдордиреЗ рдмрдЧреНрд╕ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдФрд░ рд╕рдВрджреЗрд╢ рдХреЛ рдЯреНрд╡реАрдХ рдХрд░рдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп рдмрд┐рддрд╛рдпрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЕрдиреБрднрд╡ рд╣реЛ

рдЬреЗрд╕реНрдЯ-рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдореЗрдВ рд▓рдЧрднрдЧ 60 рдорд╛рдЪрд┐рд╕ рд╣реИрдВ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдХрдИ рд╢реБрджреНрдз рдЪреАрдиреА рд╣реИрдВред рдЙрди рдореИрдЪрд░реНрд╕ рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЖрдк рд╢рд╛рдпрдж рдХрдо рд╕реЗ рдХрдо 7 рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЛ рдвреВрдВрдв рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрдиреНрд╣реЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рдкрд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рд╡рд╣ рдЕрдиреБрдорд╛рдиреА рдерд╛ рдЬрд┐рд╕реЗ рд╣рдо рдХреЛрд░ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рдереЗ рддреЛ рд╣рдо рд╢рд╛рдпрдж рдЕрдкрдирд╛ рд╕рд╛рд░рд╛ рд╕рдордп рдХреЗрд╡рд▓ рдореИрдЪрд░реНрд╕ рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдореЗрдВ рд╡реНрдпрддреАрдд рдХрд░реЗрдВрдЧреЗ

рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд╖реНрдкрдХреНрд╖ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП - рдЕрдзрд┐рдХрд╛рдВрд╢ рдореИрдЪрд░реНрд╕ рдХрд┐рд╕реА рди рдХрд┐рд╕реА рд╕реНрддрд░ рдкрд░ "рдЪреАрдиреА" рд╣реЛрддреЗ рд╣реИрдВред рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ toBeGreaterThanOrEqual expect(foo >= bar).toBe(true); рд▓рд┐рдП рд╕рд┐рд░реНрдл рдЪреАрдиреА рд╣реИ

рдореИрдЪрд░реНрд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмреВрд▓рд┐рдпрди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯреНрд╕ рдХреЗ рдЖрд╕рдкрд╛рд╕ _рд▓рдЧрднрдЧ рд╕рднреА_ рдЪреАрдиреА рд╣реИрдВ;)

(рдореИрдВ рдЗрд╕реЗ рдЦреЛрджрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд╣рддрд╛, рдХреЗрд╡рд▓ рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣... рдПрдХ рдмрд╣реБрдд рдзреБрдВрдзрд▓реА рд░реЗрдЦрд╛ рд╣реИ)

рдЬреИрд╕рд╛ рдХрд┐ abritinthebay рдиреЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдерд╛, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЪреАрдиреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдпрд╣ "рдЖрд╡рд╢реНрдпрдХ" рдФрд░ "рдЕрдирд╛рд╡рд╢реНрдпрдХ" (рдХреЛрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП) рдЪреАрдиреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рдЖрдкрдХреЗ рдкрд╛рд╕ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рд▓реЛрдЧреЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд╣реИ рдЬреЛ рдХрд╣ рд░рд╣рд╛ рд╣реИ "рдЕрд░реЗ, рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдХреБрдЫ рдРрд╕рд╛ рд╣реИ рдЬреЛ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдореВрд▓ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП" (рдпрд╛рдиреА рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ)ред

рд╣рдорд╛рд░реА рдмрд╛рдд рд╕реБрдиреЗрдВ рдпрд╛ рди рд╕реБрдиреЗрдВ, рдлрд┐рд░ рд╕реЗ рдЕрдиреБрд░рдХреНрд╖рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдкрдХреЗ рдкрд╛рд╕ рдмрд╣реБрдд рд╕реА рдЕрдиреНрдп рдЪрд┐рдВрддрд╛рдПрдБ рд╣реИрдВред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рд╕рд╣реА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ "рдЖрдкрдХрд╛ рд╕рд┐рд░реНрдл рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЪреАрдиреА рд╣реИ" (рдпрд╣ рдореИрдВ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдореБрдВрд╣ рдореЗрдВ рд╢рдмреНрдж рдбрд╛рд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ) рдЬрдм рдпрд╣ рдирд┐рд╣рд┐рдд рдирд╣реАрдВ рд╣реИ: рдпрд╣ 100% рдЖрдкрдХреА рдХреЙрд▓ рд╣реИ рдЪрд╛рд╣реЗ рдЬреЗрд╕реНрдЯ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдирд╣реАрдВред

рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ: рдкреА?

expect(Array.isArray(['your', 'array'])).toBe(true);

expect(typeof something === "object").toBe(true); 
// - or -
expect(something instanceof Object).toBe(true);

expect(typeof something === "string").toBe(true); 

@nahumzs рдЬрдмрдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЕрд╕рдлрд▓ рд╣реЛрдиреЗ рдкрд░ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рдЖрдЙрдЯрдкреБрдЯ рдкрд░, рдпрд╣ 'рдЕрдкреЗрдХреНрд╖рд┐рдд рдЭреВрдард╛ рд╕рдЪ рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж' рдХрд╣реЗрдЧрд╛, рдЬреЛ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рдирд╣реАрдВ рд╣реИ;)

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдиреЗ рдХрд╛ рд░рд╛рд╕реНрддрд╛ рд╣реИ :)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})

рдореИрдВрдиреЗ @abritinthebay рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЛрдмрд╛рд░рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреАред рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдирд╛ рдереЛрдбрд╝рд╛ рд╕рд╣рдЬ рд▓рдЧрддрд╛ рд╣реИред

```рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ
рдЙрдореНрдореАрдж.рд╡рд┐рд╕реНрддрд╛рд░({
/ ** @рдкрд░рдо { } рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ
* @рдкрд░рдо {рд╕реНрдЯреНрд░рд┐рдВрдЧ | рд╕реНрдЯреНрд░рд┐рдВрдЧ []} рддрд░реНрдХ
* @ рд╡рд╛рдкрд╕реА {{рдкрд╛рд╕: рдмреВрд▓рд┐рдпрди, рд╕рдВрджреЗрд╢: (рдлрд╝рдВрдХреНрд╢рди (): рд╕реНрдЯреНрд░рд┐рдВрдЧ)}}
*/
toBeType (рдкреНрд░рд╛рдкреНрдд, рддрд░реНрдХ) {
const isCorrectType = arg => {
рдХреЙрдиреНрд╕реНрдЯ рдкреНрд░рд╛рдкреНрдд рдЯрд╛рдЗрдк = рдЯрд╛рдЗрдкрдСрдл рдкреНрд░рд╛рдкреНрдд;

        const checkForSingle = arg => {
            const type = receivedType === 'object'
                ? Array.isArray(received)
                    ? 'array'
                    : receivedType
                : receivedType;

            return type === arg;
        };

        const checkForArr = arg => {
            const reducer = (prev, curr) => prev || isCorrectType(curr).isCorrect;

            return arg.reduce(reducer, false);
        };

        return {
            receivedType,
            isCorrect: Array.isArray(arg)
                ? checkForArr(arg)
                : checkForSingle(arg)
        };
    };

    const {isCorrect, receivedType} = isCorrectType(arg);

    return {
        pass: isCorrect,
        message: () => {
            const toBe = Array.isArray(arg)
                ? arg.join(`' or '`)
                : arg;

            return `Expected '${received}' of '${receivedType}' type to be of '${toBe}' type(s)`;
        }
    };
}

});

рдЖрдкрдХреЛ рдореЗрд░рд╛ рдореЙрдбреНрдпреВрд▓ (рдКрдкрд░ рд▓рд┐рдВрдХ) рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЙрд╕рд╕реЗ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдпрд╣ рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реЗрдВ!

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдиреЗ рдХрд╛ рд░рд╛рд╕реНрддрд╛ рд╣реИ :)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})

рдпрд╣ рднрд╡рд┐рд╖реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЕрдзрд┐рдХ рдкрдардиреАрдп рдФрд░ рд░рдЦрд░рдЦрд╛рд╡ рдпреЛрдЧреНрдп рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдиреЗ рдХрд╛ рд░рд╛рд╕реНрддрд╛ рд╣реИ :)

describe('type check', () => {
    test('should be type string', () => {
        expect(typeof '').toBe('string')
    })

    test('should be type number', () => {
        expect(typeof 10).toBe('number')
    })

    test('should be type boolean', () => {
        expect(typeof true).toBe('boolean')
    })

    test('should be type undefined', () => {
        expect(typeof undefined).toBe('undefined')
    })

    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
    })

    test('should be type function', () => {
        expect(typeof function() {}).toBe('function')
    })

    test('should be type null', () => {
        expect(typeof null).toBe('object')
    })
})
    test('should be type object', () => {
        expect(typeof { foo: 'bar' }).toBe('object')
        // passes
        expect(typeof ['foo', 'bar']).toBe('object')
        // passes
        expect(typeof null).toBe('object')
    })

рдореИрдВ

рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВ рдКрдкрд░ рдЕрдкрдиреЗ рдРрдбрдСрди рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ: рдЗрд╕рдХрд╛ рдЦреНрдпрд╛рд▓ рд░рдЦрддрд╛ рд╣реИред

рдЗрдВрд╕реНрдЯреЗрдВрд╕рдСрдл рдереЛрдбрд╝рд╛ рдмреЗрд╣рддрд░ рд╣реИ рд▓реЗрдХрд┐рди рдЗрд╕реА рддрд░рд╣ рдХреЗ рдореБрджреНрджреЛрдВ рд╕реЗ рдЧреНрд░рд╕реНрдд рд╣реИред

рдЗрд╕рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВ:

https://www.npmjs.com/package/jest-tobetype

рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж @abritinthebay

рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди:

expect('example').toEqual(expect.any(String));
expect(123).toEqual(expect.any(String));

рджреВрд╕рд░рд╛ рд╡рд╛рд▓рд╛ рдЕрд╕рдлрд▓ рд╣реЛрдЧрд╛:

    Expected: Any<String>
    Received: 123
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

hramos picture hramos  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

rosiakr picture rosiakr  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

gustavjf picture gustavjf  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

stephenlautier picture stephenlautier  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ianp picture ianp  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ