Repository: ansible/awx
File: awx/main/tests/functional/api/test_user.py (Python)

Code before:
            },
            "password_validators": [],
            "expected_status_code": 201,
        },
        # Test if password is only numeric.
        {
            "user_attrs": {
                "password": "1234567890",  # NOSONAR
                "username": "TestUser1",
                "is_superuser": False,
            },
            "password_validators": [
                {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
            ],
            "expected_status_code": 400,
        },
        {
            "user_attrs": {
                "password": "1234567890",  # NOSONAR
                "username": "TestUser1",
                "is_superuser": False,
            },
            "password_validators": [],
            "expected_status_code": 201,
        },
    ]
    for i, fixtures in enumerate(fixtures_list):
        user_attrs = fixtures.setdefault("user_attrs", default_fixtures["user_attrs"])
        password_validators = fixtures.setdefault("password_validators", default_fixtures["password_validators"])
        expected_status_code = fixtures["expected_status_code"]
        print(f"Testing fixtures {i}: {expected_status_code=} {user_attrs=}")
        with override_settings(AUTH_PASSWORD_VALIDATORS=password_validators):
            response = post(reverse('api:user_list'), user_attrs, admin, middleware=SessionMiddleware(mock.Mock()))
            assert response.status_code == expected_status_code
            # Delete user if it was created succesfully.
            if response.status_code == 201:
                response = delete(reverse('api:user_detail', kwargs={'pk': response.data['id']}), admin, middleware=SessionMiddleware(mock.Mock()))
                assert response.status_code == 204


@pytest.mark.django_db
def test_fail_double_create_user(post, admin):
    response = post(reverse('api:user_list'), EXAMPLE_USER_DATA, admin, middleware=SessionMiddleware(mock.Mock()))
    assert response.status_code == 201

    response = post(reverse('api:user_list'), EXAMPLE_USER_DATA, admin, middleware=SessionMiddleware(mock.Mock()))
    assert response.status_code == 400


@pytest.mark.django_db
def test_creating_user_retains_session(post, admin):

Review comment (bug):
Right now these don't have any visibility for a test failure. The message will say that `response.status_code` is not 201, but then you won't know which test case that is for. This is partially fixable, as a cheap fix, with:

```python
            assert response.status_code == expected_status_code, (i, fixtures)
```

This will print the loop variables along with the AssertionError.

But really, the _best_ would be to put these in `@pytest.mark.parametrize` decorator.

Code after:
    validators = validators if validators is not None else default_parameters["validators"]
    with override_settings(AUTH_PASSWORD_VALIDATORS=validators):
        response = post(reverse('api:user_list'), user_attrs, admin, middleware=SessionMiddleware(mock.Mock()))
        assert response.status_code == expected_status_code
        # Delete user if it was created succesfully.
        if response.status_code == 201:
            response = delete(reverse('api:user_detail', kwargs={'pk': response.data['id']}), admin, middleware=SessionMiddleware(mock.Mock()))
            assert response.status_code == 204
        else:
            # Catch the unexpected behavior that sometimes the user is written
            # into the database before the validation fails. This actually can
            # happen if UserSerializer.validate instantiates User(**attrs)!
            username = user_attrs['username']
            assert not User.objects.filter(username=username)


@pytest.mark.django_db
def test_fail_double_create_user(post, admin):
    response = post(reverse('api:user_list'), EXAMPLE_USER_DATA, admin, middleware=SessionMiddleware(mock.Mock()))
    assert response.status_code == 201

    response = post(reverse('api:user_list'), EXAMPLE_USER_DATA, admin, middleware=SessionMiddleware(mock.Mock()))
    assert response.status_code == 400


@pytest.mark.django_db
def test_creating_user_retains_session(post, admin):
    '''
    Creating a new user should not refresh a new session id for the current user.
    '''
    with mock.patch('awx.api.serializers.update_session_auth_hash') as update_session_auth_hash:
        response = post(reverse('api:user_list'), EXAMPLE_USER_DATA, admin)
        assert response.status_code == 201
        assert not update_session_auth_hash.called


@pytest.mark.django_db
def test_updating_own_password_refreshes_session(patch, admin):
    '''
    Updating your own password should refresh the session id.
    '''
    with mock.patch('awx.api.serializers.update_session_auth_hash') as update_session_auth_hash:
        # Attention: If the Django password validator `CommonPasswordValidator`
        # is active, this test case will fail because this validator raises on
        # password 'newpassword'. Consider changing the hard-coded password to
        # something uncommon.
        patch(reverse('api:user_detail', kwargs={'pk': admin.pk}), {'password': 'newpassword'}, admin, middleware=SessionMiddleware(mock.Mock()))
        assert update_session_auth_hash.called


@pytest.mark.django_db