org.ambraproject.admin.action.IssueManagementActionTest.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.admin.action.IssueManagementActionTest.java

Source

/*
 * $HeadURL$
 * $Id$
 * Copyright (c) 2006-2012 by Public Library of Science http://plos.org http://ambraproject.org
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ambraproject.admin.action;

import com.opensymphony.xwork2.Action;
import org.ambraproject.action.BaseActionSupport;
import org.ambraproject.admin.AdminWebTest;
import org.ambraproject.admin.service.AdminService;
import org.ambraproject.service.article.NoSuchArticleIdException;
import org.ambraproject.service.article.ArticleService;
import org.ambraproject.views.TOCArticleGroup;
import org.ambraproject.views.article.ArticleInfo;
import org.ambraproject.views.article.ArticleType;
import org.ambraproject.models.Article;
import org.ambraproject.models.Issue;
import org.ambraproject.models.Volume;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Random;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

/**
 * @author Alex Kudlick 2/1/12
 */
public class IssueManagementActionTest extends AdminWebTest {

    @Autowired
    protected IssueManagementAction action;

    @Autowired
    protected ArticleService articleService; //just using this to get articles by doi and check that they didn't get deleted

    @Autowired
    protected AdminService adminService; //just using this to format expected doi strings

    @Override
    protected BaseActionSupport getAction() {
        return action;
    }

    @DataProvider(name = "basicInfo")
    public Object[][] getBasicInfo() {
        Issue issue = new Issue();
        issue.setRespectOrder(true);
        issue.setIssueUri("id:testIssueForIssueManagement");
        issue.setDisplayName("Malbolge");
        issue.setImageUri("id:testImageForIssueManagement");
        issue.setArticleDois(new ArrayList<String>(8));

        List<TOCArticleGroup> articleGroupList = new ArrayList<TOCArticleGroup>(4);

        for (ArticleType type : ArticleType.getOrderedListForDisplay()) {
            TOCArticleGroup group = new TOCArticleGroup(type);

            for (int i = 1; i < 3; i++) {
                Article article = new Article();
                article.setDoi("id:" + type.getHeading().replaceAll(" ", "_") + "-article" + i);
                article.setTitle("Title for Article " + i + " in group " + type.getHeading());
                article.setTypes(new HashSet<String>(1));
                article.getTypes().add(type.getUri().toString());

                //ensure that articles are ordered in time
                Calendar date = Calendar.getInstance();
                date.add(Calendar.SECOND, -1 * (type.getHeading().hashCode() + i));
                article.setDate(date.getTime());

                dummyDataStore.store(article);
                issue.getArticleDois().add(article.getDoi());

                //add an articleInfo to TOC group
                ArticleInfo info = new ArticleInfo();
                info.setDoi(article.getDoi());
                info.setAt(article.getTypes());
                info.setTitle(article.getTitle());
                group.addArticle(info);
            }
            articleGroupList.add(group);
        }

        //group for orphans
        TOCArticleGroup orphans = new TOCArticleGroup(null);
        orphans.setHeading("Orphaned Article");
        orphans.setPluralHeading("Orphaned Articles");

        Article orphan1 = new Article();
        orphan1.setDoi("id:orphaned-article-for-IssueManagementAction1");
        orphan1.setTypes(new HashSet<String>(1));
        orphan1.getTypes().add("id:definitelyNotARealArticleType");
        dummyDataStore.store(orphan1);

        ArticleInfo orphan1Info = new ArticleInfo();
        orphan1Info.setDoi(orphan1.getDoi());
        orphans.addArticle(orphan1Info);
        issue.getArticleDois().add(orphan1.getDoi());

        ArticleInfo orphan2Info = new ArticleInfo();
        orphan2Info.setDoi("id:non-existent-article-orphan");
        orphans.addArticle(orphan2Info);
        issue.getArticleDois().add(orphan2Info.getDoi());

        articleGroupList.add(orphans);

        //sort the issue article list in a weird way so we can tell that the article csv is ordered by toc groups
        Collections.sort(issue.getArticleDois(), new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return -1 * o1.compareTo(o2);
            }
        });
        for (TOCArticleGroup group : articleGroupList) {
            Collections.sort(group.getArticles(), new Comparator<ArticleInfo>() {
                @Override
                public int compare(ArticleInfo o1, ArticleInfo o2) {
                    return -1 * o1.getDoi().compareTo(o2.getDoi());
                }
            });
        }
        dummyDataStore.store(issue);

        return new Object[][] { { issue, articleGroupList } };
    }

    @Test(dataProvider = "basicInfo")
    public void testExecute(Issue issue, List<TOCArticleGroup> articleGroupList) throws Exception {
        action.setIssueURI(issue.getIssueUri());
        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");

        assertEquals(action.getActionErrors().size(), 0, "Action returned error messages");
        assertEquals(action.getActionMessages().size(), 0, "Action returned messages on default request");

        assertEquals(action.getIssue().getIssueUri(), issue.getIssueUri(), "Action returned incorrect issue");
        assertEquals(action.getIssue().getDisplayName(), issue.getDisplayName(),
                "Action returned issue with incorrect display name");
        assertEquals(action.getIssue().getImageUri(), issue.getImageUri(),
                "Action returned issue with incorrect image URI");

        //the action should show the article csv in order of the article groups
        assertEquals(action.getArticleOrderCSV(), adminService.formatArticleCsv(articleGroupList),
                "Action returned incorrect article csv");

        assertEquals(action.getArticleGroups().size(), articleGroupList.size(),
                "Action returned incorrect number of article groups");
        //article groups
        for (int i = 0; i < articleGroupList.size(); i++) {
            TOCArticleGroup actualGroup = action.getArticleGroups().get(i);
            TOCArticleGroup expectedGroup = articleGroupList.get(i);
            assertEquals(actualGroup.getHeading(), expectedGroup.getHeading(),
                    "Article group " + (i + 1) + " had incorrect heading");
            assertEquals(actualGroup.getArticles().size(), expectedGroup.getArticles().size(),
                    "Article group " + (i + 1) + " had incorrect number of articles");
            //articles in the group
            for (int j = 0; j < actualGroup.getArticles().size(); j++) {
                ArticleInfo actualArticle = actualGroup.getArticles().get(j);
                ArticleInfo expectedArticle = expectedGroup.getArticles().get(j);
                assertEquals(actualArticle.getDoi(), expectedArticle.getDoi(),
                        "Article " + (j + 1) + " in group " + actualGroup.getHeading() + " had incorrect doi");
                assertEquals(actualArticle.getTitle(), expectedArticle.getTitle(),
                        "Article " + (j + 1) + " in group " + actualGroup.getHeading() + " had incorrect title");
            }
        }
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute" }, alwaysRun = true)
    public void testUpdateIssue(Issue issue, List<TOCArticleGroup> articleGroupList) throws Exception {
        //execute the action to get the current CSV
        action.setCommand("foo");
        action.setIssueURI(issue.getIssueUri());
        action.execute();
        clearMessages();

        List<String> existingArticles = dummyDataStore.get(Issue.class, issue.getID()).getArticleDois();

        String reorderedArticleCsv = action.getArticleOrderCSV();
        String articleToReorder = reorderedArticleCsv.substring(0, reorderedArticleCsv.indexOf(","));
        reorderedArticleCsv = reorderedArticleCsv.replaceFirst(articleToReorder + ",", "");
        reorderedArticleCsv += ("," + articleToReorder);
        String[] orderedArticlesForDb = reorderedArticleCsv.split(",");

        //when we tell the action to order the articles in the issue, it does, but then they are grouped by types
        List<String> orderedArticlesForCSV = new ArrayList<String>(existingArticles.size());
        for (ArticleType type : ArticleType.getOrderedListForDisplay()) {
            for (String article : orderedArticlesForDb) {
                try {
                    if (articleService.getArticle(article, DEFAULT_ADMIN_AUTHID).getTypes()
                            .contains(type.getUri().toString())) {
                        orderedArticlesForCSV.add(article);
                    }
                } catch (NoSuchArticleIdException e) {
                    //suppress
                }
            }
        }
        for (String article : orderedArticlesForDb) {
            if (!orderedArticlesForCSV.contains(article)) {
                orderedArticlesForCSV.add(article);
            }
        }

        String imageUri = "id:newImageURIToSetOnIssue";
        String displayName = "Cheech and Chong";

        action.setCommand("UPDATE_ISSUE");
        action.setIssueURI(issue.getIssueUri());
        action.setArticleOrderCSV(reorderedArticleCsv);
        action.setDisplayName(displayName);
        action.setImageURI(imageUri);
        action.setRespectOrder(true);

        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");

        assertEquals(action.getActionErrors().size(), 0, "Action returned error messages");
        assertTrue(action.getActionMessages().size() > 0, "Action didn't return messages indicating success");

        //check properties on action
        assertEquals(action.getIssue().getIssueUri(), issue.getIssueUri(), "action changed issues after update");
        assertEquals(action.getDisplayName(), displayName, "action had incorrect display name");
        assertEquals(action.getImageURI(), imageUri, "Action had incorrect image uri");
        assertEquals(action.getArticleOrderCSV(), StringUtils.join(orderedArticlesForCSV, ","),
                "action didn't have correct article csv");

        //check what got stored to the database
        Issue storedIssue = dummyDataStore.get(Issue.class, issue.getID());

        assertEquals(storedIssue.getDisplayName(), displayName,
                "Issue got saved to the database with incorrect display name");
        assertEquals(storedIssue.getImageUri(), imageUri,
                "Issue got saved to the database with incorrect image uri");
        assertEquals(storedIssue.getArticleDois().size(), existingArticles.size(),
                "Articles got removed or added from the issue on reordering");

        //The db, however, stores articles in the order we told it
        for (int i = 0; i < orderedArticlesForDb.length; i++) {
            assertEquals(storedIssue.getArticleDois().get(i), orderedArticlesForDb[i],
                    "Articles didn't get ordered correctly in the database; article " + (i + 1) + " was incorrect");
        }
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute" }, alwaysRun = true)
    public void testActionDoesNotAllowAddingArticleToCsv(Issue issue, List<TOCArticleGroup> articleGroupList)
            throws Exception {
        //execute the action to get the original csv
        action.setIssueURI(issue.getIssueUri());
        action.execute();
        String originalCsv = action.getArticleOrderCSV();

        String incorrectCsv = originalCsv + ",id:some-fake-new-article";

        action.setCommand("UPDATE_ISSUE");
        action.setArticleOrderCSV(incorrectCsv);
        action.setRespectOrder(true);
        action.setDisplayName(issue.getDisplayName());
        action.setImageURI(issue.getImageUri());

        //should fail
        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");
        assertTrue(action.getActionErrors().size() > 0, "Action didn't return error messages");
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute" }, alwaysRun = true)
    public void testActionDoesNotAllowRemovingArticleFromCsv(Issue issue, List<TOCArticleGroup> articleGroupList)
            throws Exception {
        //execute the action to get the original csv
        action.setIssueURI(issue.getIssueUri());
        action.execute();
        String originalCsv = action.getArticleOrderCSV();

        String articleToRemove = originalCsv.substring(0, originalCsv.indexOf(","));
        String incorrectCsv = originalCsv.replace(articleToRemove + ",", "");

        action.setCommand("UPDATE_ISSUE");
        action.setArticleOrderCSV(incorrectCsv);
        action.setRespectOrder(true);
        action.setDisplayName(issue.getDisplayName());
        action.setImageURI(issue.getImageUri());

        //should fail
        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");
        assertTrue(action.getActionErrors().size() > 0, "Action didn't return error messages");
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute" }, alwaysRun = true)
    public void testActionDoesNotAllowChangingArticlesInCsv(Issue issue, List<TOCArticleGroup> articleGroupList)
            throws Exception {
        //execute the action to get the original csv
        action.setIssueURI(issue.getIssueUri());
        action.execute();
        String originalCsv = action.getArticleOrderCSV();

        String changedCsv = originalCsv.substring(originalCsv.indexOf(",") + 1);
        changedCsv = "id:this-article-was-not-in-original-csv," + changedCsv;

        assertEquals(changedCsv.split(",").length, originalCsv.split(",").length,
                "test added or removed articles instead of just changing one");

        action.setCommand("UPDATE_ISSUE");
        action.setArticleOrderCSV(changedCsv);
        action.setRespectOrder(true);
        action.setDisplayName(issue.getDisplayName());
        action.setImageURI(issue.getImageUri());

        //should fail
        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");
        assertTrue(action.getActionErrors().size() > 0, "Action didn't return error messages");
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute", "testUpdateIssue" }, alwaysRun = true)
    public void testAddArticle(Issue issue, List<TOCArticleGroup> articleGroupList) throws Exception {
        String articlesToAddCsv = "id:new-article-for-adding-to-issue1,id:new-article-for-adding-to-issue2";
        Article article = new Article();
        article.setDoi(articlesToAddCsv.split(",")[0]);
        article.setTypes(new HashSet<String>(1));
        article.getTypes().add(ArticleType.getOrderedListForDisplay().get(0).getUri().toString());
        article.setDate(Calendar.getInstance().getTime());
        dummyDataStore.store(article);

        action.setCommand("ADD_ARTICLE");
        action.setIssueURI(issue.getIssueUri());
        action.setArticlesToAddCsv(articlesToAddCsv);

        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");

        assertEquals(action.getActionErrors().size(), 0, "Action returned error messages");
        assertEquals(action.getActionMessages().size(), 1, "Action didn't return messages indicating success");

        for (String doi : articlesToAddCsv.split(",")) {
            assertTrue(action.getArticleOrderCSV().contains(doi),
                    "Article " + doi + " didn't get added to action's csv");
            assertTrue(action.getIssue().getArticleDois().contains(doi),
                    "Article " + doi + " didn't get added to action's issue");
        }
        //the first article should be in the first TOC group
        boolean foundMatch = false;
        for (ArticleInfo articleInfo : action.getArticleGroups().get(0).getArticles()) {
            if (articleInfo.getDoi().equals(article.getDoi())) {
                foundMatch = true;
                break;
            }
        }
        assertTrue(foundMatch, "New article didn't get added to correct group");
        String orphanDoi = articlesToAddCsv.split(",")[1];
        //the second article should be an orphan
        ArrayList<ArticleInfo> orphans = action.getArticleGroups().get(action.getArticleGroups().size() - 1)
                .getArticles();
        boolean foundOrphan = false;
        for (ArticleInfo articleInfo : orphans) {
            if (orphanDoi.equals(articleInfo.getDoi())) {
                foundOrphan = true;
                break;
            }
        }
        assertTrue(foundOrphan, "Non existent article didn't get added to orphan list");

        //check the values that got stored to the database
        List<String> storedArticles = dummyDataStore.get(Issue.class, issue.getID()).getArticleDois();
        for (String doi : articlesToAddCsv.split(",")) {
            assertTrue(storedArticles.contains(doi),
                    "Article " + doi + " didn't get added to the issue in the database");
        }
    }

    @Test(dataProvider = "basicInfo", dependsOnMethods = { "testExecute" }, alwaysRun = true)
    public void testRemoveArticles(Issue issue, List<TOCArticleGroup> articleGroupList) throws Exception {
        List<String> articlesToDelete = dummyDataStore.get(Issue.class, issue.getID()).getArticleDois().subList(0,
                3);
        String[] articlesToDeleteArray = new String[3];
        for (int i = 0; i < 3; i++) {
            articlesToDeleteArray[i] = articlesToDelete.get(i);
        }

        action.setCommand("REMOVE_ARTICLES");
        action.setIssueURI(issue.getIssueUri());
        action.setArticlesToRemove(articlesToDeleteArray);

        String result = action.execute();
        assertEquals(result, Action.SUCCESS, "Action didn't return success");

        assertEquals(action.getActionErrors().size(), 0, "Action returned error messages");
        assertEquals(action.getActionMessages().size(), 1, "Action didn't return messages indicating success");

        for (String doi : articlesToDelete) {
            assertFalse(action.getIssue().getArticleDois().contains(doi),
                    "Article " + doi + " didn't get removed from action's issue list");
            assertFalse(action.getArticleOrderCSV().contains(doi),
                    "Article " + doi + " didn't get removed from action's csv");
        }

        //check the values in the db
        List<String> storedArticleList = dummyDataStore.get(Issue.class, issue.getID()).getArticleDois();
        for (String doi : articlesToDelete) {
            assertFalse(storedArticleList.contains(doi),
                    "Article " + doi + " didn't get removed from issue in the database");
            try {
                articleService.getArticle(doi, DEFAULT_ADMIN_AUTHID);
            } catch (NoSuchArticleIdException e) {
                fail("Article " + doi
                        + " got deleted from the database instead of just being removed from the issue");
            }
        }
    }
}