//@flow
/* eslint-disable camelcase */
import React from 'react';
import { act, create } from 'react-test-renderer';

import GAProvider from './ga-provider.jsx';
import UserProvider from './user-provider.jsx';

describe('UserProvider', () => {
    test('context works', () => {
        const P = UserProvider.context.Provider;
        const C = UserProvider.context.Consumer;
        const contextConsumer = jest.fn();
        const userData = {
            ...UserProvider.defaultUserData,
            username: 'testing',
        };

        create(
            <P value={userData}>
                <C>{contextConsumer}</C>
            </P>
        );

        // We expect that the consumer <C> will get the user data from
        // the provider <P> and pass it to the child function. This is
        // just verifying that we're using the React context API correctly.
        expect(contextConsumer.mock.calls.length).toBe(1);
        expect(contextConsumer.mock.calls[0][0]).toEqual(userData);
    });

    // This test passes but causes a warning message from
    // react-test-render about needing to make changes inside of an
    // act() call. Unfortunately, the change in question appears to be
    // the asyncronous resolution of the json promise, and I can't get
    // the warning to go away even with a really convoluted fetch()
    // mock. I think this is related to
    // https://github.com/facebook/react/issues/14769 and hopefully a
    // version of act() that can take async methods will fix the
    // issue.
    test('Provider fetches user data and waffle flags', (done) => {
        const P = UserProvider;
        const C = UserProvider.context.Consumer;
        const contextConsumer = jest.fn();

        const waffleFlags = {
            flags: { section_edit: true },
            switches: {},
            samples: {},
        };

        const userData = {
            ...UserProvider.defaultUserData,
            username: 'testing',
            isAuthenticated: true,
            isStaff: true,
            waffle: waffleFlags,
            email: 'testuser@mail.com',
        };

        // In this test we want to verify that UserProvider is
        // fetching user data from an API. So we need to mock fetch().
        global.fetch = jest.fn(() => {
            return Promise.resolve({
                json: () =>
                    Promise.resolve({
                        username: 'testing',
                        is_authenticated: true,
                        is_staff: true,
                        waffle: waffleFlags,
                        email: 'testuser@mail.com',
                    }),
            });
        });

        let gaMock = (window.ga = jest.fn());

        act(() => {
            create(
                <GAProvider>
                    <P>
                        <C>{contextConsumer}</C>
                    </P>
                </GAProvider>
            );
        });

        // To start, we expect the contextConsumer function to be called
        // with the default null value. And we expect our fetch() mock to
        // be called when the component is first mounted, too.
        // At this point we don't expect any GA calls
        expect(contextConsumer).toHaveBeenCalledTimes(1);
        expect(contextConsumer).toHaveBeenCalledWith(null);
        expect(global.fetch).toHaveBeenCalledTimes(1);
        expect(global.fetch).toHaveBeenCalledWith('/api/v1/whoami');
        expect(gaMock).toHaveBeenCalledTimes(0);

        // After the fetch succeeds, we expect contextConsumer to be
        // called again with the fetched userdata. And we expect some
        // data to have been sent to the ga() function
        process.nextTick(() => {
            expect(contextConsumer).toHaveBeenCalledTimes(2);
            expect(contextConsumer.mock.calls[1][0]).toEqual(userData);
            expect(gaMock).toHaveBeenCalledTimes(4);
            expect(gaMock.mock.calls[0]).toEqual(['set', 'dimension1', 'Yes']);
            expect(gaMock.mock.calls[1]).toEqual(['set', 'dimension18', 'Yes']);
            expect(gaMock.mock.calls[2]).toEqual(['set', 'dimension9', 'Yes']);
            expect(gaMock.mock.calls[3][0]).toEqual('send');
            expect(gaMock.mock.calls[3][1].hitType).toEqual('pageview');
            done();
        });
    });
});

@@ -72,47 +72,54 @@
 t %7B 
-act, create %7D from 'react-test-renderer
+render, waitFor %7D from '@testing-library/react
 ';%0A%0A
@@ -536,38 +536,38 @@
     %7D;%0A%0A        
-c
 re
-ate
+nder
 (%0A            %3CP
@@ -1594,13 +1594,15 @@
 s', 
-(done
+async (
 ) =%3E
@@ -2259,22 +2259,22 @@
         
-global
+window
 .fetch =
@@ -2282,23 +2282,46 @@
 jest.fn(
+).mockImplementationOnce(
 () =%3E
- %7B
 %0A       
@@ -2329,15 +2329,8 @@
     
-return 
 Prom
@@ -2335,32 +2335,58 @@
 omise.resolve(%7B%0A
+                ok: true,%0A
                 
@@ -2699,25 +2699,24 @@
           %7D)
-;
 %0A        %7D);
@@ -2704,33 +2704,32 @@
      %7D)%0A        
-%7D
 );%0A%0A        let 
@@ -2775,43 +2775,16 @@
     
-act(() =%3E %7B%0A            create(%0A   
+render(%0A
     
@@ -2791,17 +2791,16 @@
         
- 
 %3CGAProvi
@@ -2824,20 +2824,12 @@
     
-    %3CP%3E%0A    
+%3CP%3E%0A
     
@@ -2881,37 +2881,29 @@
             
-    
 %3C/P%3E%0A
-    
             
@@ -2928,24 +2928,8 @@
     
-    );%0A        %7D
 );%0A%0A
@@ -3192,16 +3192,50 @@
 A calls%0A
+        await waitFor(() =%3E %7B%0A    
         
@@ -3276,32 +3276,36 @@
 CalledTimes(1);%0A
+    
         expect(c
@@ -3348,32 +3348,36 @@
 (null);%0A        
+ 
+   
 expect(global.fe
@@ -3399,32 +3399,36 @@
 CalledTimes(1);%0A
+    
         expect(g
@@ -3480,32 +3480,36 @@
 oami');%0A        
+ 
+   
 expect(gaMock).t
@@ -3532,16 +3532,28 @@
 imes(0);
+%0A        %7D);
 %0A%0A      
@@ -4258,24 +4258,24 @@
 al('send');%0A
+
             
@@ -4339,28 +4339,8 @@
 ');%0A
-            done();%0A
     

Fix Jest error in user-provider test (#6969)