text:
Out of Town Attractions
Prague Attractions
Prague Zoo raising parking fees
Officials hope more people will use public transportation
by Raymond Johnston - Prague.TV (Foto: Zoo Praha)
The popularity of Prague Zoo has been growing from year to year, and it is the city's second-most popular attraction. But not only is the size of the parking lot the same as it was in the past, more people are driving there in cars.
To encourage people to use public transportation more, the zoo will soon be raising the parking rate to Kč 200 per day for cars. Currently it is Kč 100.
As of May 1, prices will go up on weekends and public holidays, but in July and August it will apply to weekdays as well. The price of the annual pass, which allows for parking on 12 days, will also go up from Kč 600 to Kč 900.
The lot has long been inadequate, and the entire Troja neighborhood often becomes congested with zoo visitors' cars. Last summer, cars had to be diverted from the area several times to other neighborhoods.
Zoo director Miroslav Bobek said the zoo has to address the problem. One solution is to discourage parking by making it more expensive. He also said there were more options to reach the zoo than buses. There is also a ferry that goes there.
The zoo is trying to make more parking spaces in some areas, but the results will be limited and not enough to meet even the current demand.
There are also plans to increase parking near the Blanka Tunnel, which has an entrance close to the zoo. This has been tested but is not in operation yet, and City Hall now says that the Blanka lot will be in a different location altogether and not where it had been tested. The groundwork for a new lot is just being made, so it will be some time before it is ready.
The zoo would like to see a tram connection that leads to the northern part of the zoo, but that is also in the far future. Zoo director Bobek said he would like to see it completed before the 100th anniversary of the zoo, which would be in 2031.
The zoo recently welcomed its 60 millionth visitor since it opened 86 years ago. His name was Vlastimil Čermák and he was from Prague. He said he comes every year and he likes the elephants and giraffes. It was in 1975 that the saw saw its 25 millionth visitor. In 1931, when it opened just 20,000 people visited. Last year that grew to 1,448,353 people in a single year.
Prague Zoo was ranked the fourth-best in the world by users of the travel site TripAdvisor in July 2015, beaten only by zoos in San Diego, California; Puerto de la Cruz, Spain; and Singapore.
Aside from two baby elephants born in 2016, other births last year included an aardvark, a giraffe, a gorilla, a viper, a rare giant rat and a rare African openbill. The zoo saw a total of 1,191 juveniles in 223 species. The zoo also has been drawing crowds to see rare lions that it acquired at the end of 2015.
Prague Zoo opened in 1931. It currently covers 58 hectares with 50 hectares used for exhibits. It has over 4,700 animals from 681 species, including 144 species listed as threatened. The zoo has 12 pavilions and over 150 exhibits. It has been particularly active in the preservation of the Przewalski's horses, which are slowly being returned to the wild.
Exploring Places: Trosky Castle by Narmin Ismiyeva
Trying to reach the Trosky castle on a bicycle might be tricky, especially if you've never ridden one. Luckily there are other ways to conquer the 14th century landmark of Bohemian Paradise.
National Museum's famous whale returns by Raymond Johnston - Prague.TV (Foto: nm.cz)
The museum also has a nightly light show outside and a new ticket policy
Navalis celebrates St Jan Nepomuk by Raymond Johnston - Prague.TV (Foto: Navalis FB)
The annual festival takes place around Charles Bridge on May 15
Action Park, place for parties and events in Prague by Paul Lysek - Prague.TV (Foto: Action Park)
The growing Action Park, Prague – adrenaline, action, fun, and outdoors – just in time for summer!
NEW HIDDEN GEMS IN PRAGUE: BEER, COFFEE, MUSEUM (Honest Guide) by Honza Mikulka & Janek Rubeš
New cool places in Prague you should definitely check out
Spanish Synagogue to close for renovation by Raymond Johnston - Prague.TV (Foto: Prague.eu)
The building will reopen at the end of 2020 with modern interactive exhibits
Plzeň celebrates its World War II liberation by Raymond Johnston - Prague.TV (Foto: slavnostisvobody.cz)
Free concerts, a military convoy and a parachuting competition are highlights
PRAGUE CASTLE FOR DUMMIES (Honest Guide) by Honza Mikulka & Janek Rubeš
Here's the number one tip you need when visiting the Prague Castle
Výstaviště renovations taking shape by Raymond Johnston - Prague.TV
The city is making progress with transforming the neglected Exhibition Grounds
Fire restrictions lifted by Raymond Johnston - Prague.TV (Foto: fotolia)
Witches Night bonfires can take place as planned
The Prague Venice company
Balloon Adventures Prague
Welcome to the ballooning world!
Prague Boats
Prague river cruises – popular Prague tourist attractions
SolvePrague
Escape rooms in Prague


text:
Q: Trying to form an Elasticsearch query for autocomplete I've read a lot and it seems that using EdgeNGrams is a good way to go for implementing an autocomplete feature for search applications. I've already configured the EdgeNGrams in my settings for my index.
PUT /bigtestindex
{
  "settings":{
    "analysis":{
      "analyzer":{
        "autocomplete":{
          "type":"custom",
          "tokenizer":"standard",
          "filter":[ "standard", "stop", "kstem", "ngram" ]
        }
      },
      "filter":{
        "edgengram":{
          "type":"ngram",
          "min_gram":2,
          "max_gram":15
        }
      },
      "highlight": {
      "pre_tags" : [""],
      "post_tags" : [""],
        "fields": {
          "title.autocomplete": {
            "number_of_fragments": 1,
            "fragment_size": 250
          }
        }
      }
    }
  }
}

So if in my settings I have the EdgeNGram filter configured how do I add that to the search query?
What I have so far is a match query with highlight:
GET /bigtestindex/doc/_search
{
  "query": {
    "match": {
      "content": {
        "query": "thing and another thing",
        "operator": "and"
      }
    }
  },
  "highlight": {
    "pre_tags" : [""],
    "post_tags" : [""],
    "field": {
      "_source.content": {
        "number_of_fragments": 1,
        "fragment_size": 250
      }
    }
  }
}

How would I add autocomplete to the search query using EdgeNGrams configured in the settings for the index?
UPDATE
For the mapping, would it be ideal to do something like this:
"title": {
        "type": "string",
        "index_analyzer": "autocomplete",
        "search_analyzer": "standard"
      },

Or do I need to use multi_field type:
"title": {
        "type": "multi_field",
        "fields": {
          "title": {
            "type": "string"
          },
          "autocomplete": {
            "analyzer": "autocomplete",
            "type": "string",
            "index": "not_analyzed"
          }
        }
     },

I'm using ES 1.4.1 and want to use the title field for autocomplete purposes.... ?

A: Short answer: you need to use it in a field mapping. As in:
PUT /test_index
{
   "settings": {
      "analysis": {
         "analyzer": {
            "autocomplete": {
               "type": "custom",
               "tokenizer": "standard",
               "filter": [
                  "standard",
                  "stop",
                  "kstem",
                  "ngram"
               ]
            }
         },
         "filter": {
            "edgengram": {
               "type": "ngram",
               "min_gram": 2,
               "max_gram": 15
            }
         }
      }
   },
   "mappings": {
      "doc": {
         "properties": {
            "field1": {
               "type": "string",
               "index_analyzer": "autocomplete",
               "search_analyzer": "standard"
            }
         }
      }
   }
}

For a bit more discussion, see:
http://blog.qbox.io/multi-field-partial-word-autocomplete-in-elasticsearch-using-ngrams
and
http://blog.qbox.io/an-introduction-to-ngrams-in-elasticsearch
Also, I don't think you want the "highlight" section in your index definition; that belongs in the query.
EDIT: Upon trying out your code, there are a couple of problems with it. One was the highlight issue I already mentioned. Another is that you named your filter "edgengram", even though it is of type "ngram" rather than type "edgeNGram", but then you referenced the filter "ngram" in your analyzer, which will use the default ngram filter, which probably doesn't give you what you want. (Hint: you can use term vectors to figure out what your analyzer is doing to your documents; you probably want to turn them off in production, though.)
So what you actually want is probably something like this:
PUT /test_index
{
   "settings": {
      "analysis": {
         "analyzer": {
            "autocomplete": {
               "type": "custom",
               "tokenizer": "standard",
               "filter": [
                  "standard",
                  "stop",
                  "kstem",
                  "edgengram_filter"
               ]
            }
         },
         "filter": {
            "edgengram_filter": {
               "type": "edgeNGram",
               "min_gram": 2,
               "max_gram": 15
            }
         }
      }
   },
   "mappings": {
      "doc": {
         "properties": {
            "content": {
               "type": "string",
               "index_analyzer": "autocomplete",
               "search_analyzer": "standard"
            }
         }
      }
   }
}

When I indexed these two docs:
POST test_index/doc/_bulk
{"index":{"_id":1}}
{"content":"hello world"}
{"index":{"_id":2}}
{"content":"goodbye world"}

And ran this query (there was an error in your "highlight" block as well; should have said "fields" rather than "field")"
POST /test_index/doc/_search
{
   "query": {
      "match": {
         "content": {
            "query": "good wor",
            "operator": "and"
         }
      }
   },
   "highlight": {
      "pre_tags": [
         ""
      ],
      "post_tags": [
         ""
      ],
      "fields": {
         "content": {
            "number_of_fragments": 1,
            "fragment_size": 250
         }
      }
   }
}

I get back this response, which seems to be what you're looking for, if I understand you correctly:
{
   "took": 5,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 0.2712221,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "2",
            "_score": 0.2712221,
            "_source": {
               "content": "goodbye world"
            },
            "highlight": {
               "content": [
                  "goodbye world"
               ]
            }
         }
      ]
   }
}

Here is some code I used to test it out:
http://sense.qbox.io/gist/3092992993e0328f7c4ee80e768dd508a0bc053f

redpajama_set_name: RedPajamaStackExchange


text:
Searching for: "Teddy Hamilton"
This new collection of romantic stories from your favorite romance writers, performed by popular narrators, features sexy little scenes to whet your appetite. Authors romance you with stories inspired by some of their bestselling works. While they may be quick pieces, they're packed with passion. Some of the stories are fun, some of them are naughty, and some of them are just plain filthy. This collection is only available in audiobook, so grab those headphones! Featured Writers: A L Jackson, Aly Martinez, Blair Babylon, Carrie Ann Ryan, Corrinne Michaels, Elle Kennedy, Julia Kent, Helena Hunting, K Webster, Kate Canterbary, Kennedy Ryan, Nana Malone, Rebecca Yarros, Sarina Bowen,...read more
Limitless Love
Audrey Carlan
I'm a good person. At least I try to be. After my husband left me, I picked up the pieces of my broken heart and tried to move on. One shattered piece at a time. Just when I thought things were looking up, that I had suffered enough at the hands of fate, my past came back with nothing to lose and a blade that cut...deep. Figuratively and physically scarred, I had nothing left to hold on to. That's when Clayton Hart entered my world. With his blue eyes, spikey blond hair, and a body packed with muscles, I never stood a chance. Clayton pushed his way into my life, my bed, and my heart, proving that only the truest love can be...read more
Dirty Exes
Rachel Van Dyken
They're serving up some red-hot revenge. A sizzling series from #1 New York Times bestselling author Rachel van Dyken. Blaire has never quite gotten over Jessie Beckett, the ex–NFL star whose kisses were hot enough to ignite the entire Eastern Seaboard. When he chose work over her, Blaire was left brokenhearted. Why else would she have married a skeezy two-timer, just to divorce him less than a year later? Now Blaire is getting even by becoming one half of Dirty Exes, a PI firm fully committed to humiliating cheating jerks. If only the new jerk she's been hired to uncover wasn't Jessie Beckett himself. Exposing Jessie isn't going to be easy, especially...read more
Dangerous Exes
In #1 New York Times bestselling author Rachel van Dyken's scorching series, revenge is a justified pleasure… Isla made one teeny little mistake. Now she and her PI company, Dirty Exes, are being targeted by one seriously angry and furiously sexy ex-quarterback. Jessie freakin' Beckett. But there's no way some NFL superhunk is going to take her business away. If only he didn't make her so hot—and bothered. Jessie wants payback for a ruined reputation. His plan? Top secret. His hard-to-hide arousal for Isla? Not so much. Especially when they let down their guards and sneak a kiss. Like any juicy scandal, it goes so viral, so fast, that only a good...read more
Misadventures with a Country Boy
Elizabeth Hayley
Brooke Devereaux has a lot she wants to escape from: a career she never asked for, a future she doesn't want, and parents who've only ever seen her as a business opportunity. But in her desire to experience life, she quickly realizes she's lacking in one very important skill—how to survive on her own. Former soldier Cole Timmons is an expert at running away. Whether it's from his rural hometown, alcoholic father, or painful memories, Cole doesn't hesitate to leave… Until he encounters an out-of-place woman at a gas station in the middle of nowhere. The wealthy "princess" couldn't be more different from the country loner, and the...read more
Sexy Jerk
Kim Karr
Everyone I know is married. It doesn't bother me. I like my life the way it is. But since I'm single, when my best friend and her husband finally decide to go on their dream honeymoon, she asks me to watch their three-year-old son, Max. Of course, I say yes. But what my best friend neglects to tell me is that I won't be babysitting alone. Thinking that Max might be too much for me to handle, her husband asks his only single friend, Nick, to help. Nick Carrington and I have met a couple of dozen times. I've never really given him a second thought—other than to say that he's kind of a jerk. Out loud. So he can hear. Sure, he's tall, dark, and handsome and has the best ass I've ever seen....read more
Until We're More
Chelsea is smart, funny, gorgeous, and the best friend I've ever had. Ever since she left, I've been a wreck. I've been focused on keeping my family's MMA gym afloat while I train and coach fighters, anything to not miss her more. But now she's finally back, along with her grumpy, possessive cat, and things are weird between us. By weird, I mean I can't stop thinking about her in that way. She's in the room next door, and it takes all my control not to storm in there, sweep her up, and bring her back to my bed. Even stranger, I'm pretty sure she'd be into it. And this time, I'm not going to stop fighting until we're more....read more
Jace Bennett is the kind of man you'll love forever. Tall, dark, and brooding, he makes your lashes flutter and your heart pound. It could be that slow, sexy smile or his filthy, dirty mouth. It could be the way he makes you feel like you're the only one who matters. Or maybe it's because just one smoldering look makes you go weak in the knees. I haven't seen him since the day I walked away. And yet seeing him now, I can't deny I want him back. No matter how much time passes, he'll always be the hot college guy sitting on the counter at a frat house drinking a beer...the one I knew I wanted to marry before I said hello. But from what I can tell, to him, I'm just somebody he used to...read more
The NFL is full of rules—rules I've never broken, never challenged, never even scratched...until the day Lucas Carrington crashes into my life with his hard body and I-don't-give-a-f*ck attitude. After I almost injure my father's star player, I volunteer to make sure he's in top shape. At first, it's hell. I don't like his cockiness, his easy smile. I don't like the way he oozes sex—or how his penetrating eyes follow me everywhere. But that doesn't stop me from wanting him. He's meant to be a distraction—something to occupy my mind for these precious few remaining hot summer nights before I'm forced to leave football behind forever. I know what we're doing will lead nowhere good. I...read more
Misadventures of a Curvy Girl
Sierra Simone
'Such a great story about self-doubt and self-confidence, but most importantly loving yourself, inside and outside.' ~Sharing My Book Boyfriends For the first time in her life, Ireland Mills is happy with her body. No more fad diets, no more hiding from every camera in the room, no more low self-esteem. She'd rather be alone than with someone who'll only love her if she's skinny. Caleb Carpenter and Ben Weber are everything Ireland and the Kansas Chamber of Commerce dreamed of when conceptualizing the "Real Kansas" promotional campaign. They're handsome, young, educated, and totally dedicated to their small prairie town. When Ireland's Prius gets...read more
The New York Times bestselling author of Pucked and The Good Luck Charm delivers a Hollywood happily-ever-after where a famous heartthrob falls for his ultimate fangirl. "As charming as its title, but it's also so much more... Fans of Jasmine Guillory's The Wedding Date and Helen Hoang's The Kiss Quotient will love Meet Cute." --The Washington Independent Review of Books Kailyn Flowers was always calm, rational, and controlled--until she ended up sprawled all over Daxton Hughes, the former actor she totally crushed on as a teenager. Then she did the unthinkable: She became a mortifying fangirl in five seconds flat, which may or may not have included professing...read more
Center of Gravity
K.K. Allen
LEX I came to L.A. with dreams bigger than me: to learn from the best choreographers in the business and secure a professional dance gig working for Hollywood's elite. Everything was going according to plan—until I was literally shoved into the arms of the one man who could make or break my career. Come to find out, it wasn't my career I had to worry about. It was my heart. THEO Everything about Alexandra Lex Quinn screamed amateur, save for the way she moved across the dance floor. She was athleticism and grace, precision and passion, and she had a stage presence I couldn't tear my eyes from. I wanted her...on my team, in my bed. There was only one problem...I couldn't have...read more
Fall in love with this hilarious and heartwarming USA Today bestselling romantic comedy that LJ Shen calls 'an absolute treat.' Kristen Peterson doesn't do drama, will fight to the death for her friends, and has no room in her life for guys who just don't get her. She's also keeping a big secret: facing a medically necessary procedure that will make it impossible for her to have children. Planning her best friend's wedding is bittersweet for Kristen -- especially when she meets the best man, Josh Copeland. He's funny, sexy, never offended by her mile-wide streak of sarcasm, and always one chicken enchilada ahead of her hangry. Even her dog, Stuntman Mike, adores him. The only catch: Josh...read more
Fiona Cole
Jake was my best friend in college—my very straight best friend—until one night he was more. He may have run after what happened between us, but I never forgot him. When fate puts us in the same place, five years later, he has a fiancé by his side. Carina is beautiful, driven, and draws my attention almost as much as he still does. A game of truth or dare leads to a wild night and a relationship that has all our feelings growing into something bigger than any of us intended. But what happens when our feelings deepen? Can I handle being with two people? If it means I can have him, I'll love them...read more
Piece of Work
Staci Hart
His body is as chiseled as Adonis. His lips are as sculpted as David. And his ego is the size of the Guggenheim. You know the type: wolfish smile and the gravity of a black hole—the kind of man who sucks all the air from the room the second he enters it. My cocky boss thinks this internship was wasted on me, and he doesn't hesitate to let me know. But he's wrong, and I'm going to prove it to him. If I can stay away from his devil lips, that is, lips that cut me down and kiss me in the same breath, leaving me certain he's on a mission to ruin my life… …and maybe my...read more
All I Ask
Fans of Christina Lauren, Colleen Hoover, and Jill Santopolo will love this breathtaking story about first love, second chances, and starting over from New York Times bestselling author Corine Michaels. Teagan Berkeley is trying her best. A single mom raising a precocious teen, she may have given up on her dreams, but she's accepted her life in her small beachside hometown. Now the one person who abandoned her when she needed him the most has returned, bringing back memories of what might have been. Derek Hartz arrives in town with a teenage daughter-and he's full of guilt over his failed marriage and the way he ended his friendship with Teagan. He's determined to set things right with...read more
Wound Tight
When CEO Renner Bastion walks into a room, everyone keeps their distance—well, everyone but the sarcastic tattooed Boston-bred security guard whose presence has kept Renner in New Jersey longer than intended. As if the unwanted attraction isn't unsettling enough, Renner finds out his protector isn't as unavailable as he originally thought. Milo Bautista just came out to his wealthy ultra-confident boss, a man he secretly respects and admires…in more ways than he'll admit. Worldly, experienced Renner would never look in his direction, let alone share some of that confidence he wears like a cloak, so Milo has set his sights on someone else to be his first. But then Renner offers...read more
Best of Me
L.K. Farlow
For as long as I can remember, I've been the dark to my sister's light—the awkward loner to her social butterfly. Growing up, she had it all: our parent's unyielding approval, perfect grades, a permanent spot at the popular table, and the attention of the hottest guy ever—Duke Kincaid. After eighteen years of living in her shadow, I couldn't wait to escape—to finally be my own person. Yet here I am—back in my hometown, once again in Valorie's shadow. Only now, it's eternal. I had life all planned out: join the force, marry Valorie Parsons, and start a family of our own. I have the job, but the girl and all my dreams died before my very eyes. Finally ready to move on, I...read more
He plays the bass with expert fingers. He plays women with intoxicating charm. And he'll play me with the ease of a virtuoso. Who better to teach me to play than the master himself? I'm his model student, front row, pencil sharp. Pick-up lines? I've got them. Free drinks? By the dozen. Kissing? Let me grab my chapstick. But the most valuable lesson I've learned is that there's so much I don't know—like why his touch sets off a chain reaction straight to my nethers…or how I'm certain each kiss is the best I'll ever have…until the moment his lips take mine again. There's so much I don't know…like the fact that I'm only a bet. But we are what we are, and he's a...read more
Here I stand, clutching a bouquet of pale pink roses behind the doors of a Las Vegas chapel, and at the end of the aisle is the absolute last man I imagined would be waiting for me. Thomas Bane. Bestselling author. Notorious bad boy. Savagely handsome, dark as sin, chiseled as stone. And, somehow, my soon-to-be husband. Marry him, and I'll land my dream job. Save him, and I'll walk away with everything I've ever wanted. All I have to do is remember it's all for show. None of it is real, no matter how real it feels. But first, I have to survive the kiss. And with lips like his, I don't stand a...read more

redpajama_set_name: RedPajamaCommonCrawl


text:
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @enum {string}
 * @const
 */
var EntryType = Object.freeze({
  FILE: 'file',
  DIRECTORY: 'directory'
});

/**
 * @enum {string}
 * @const
 */
var SharedOption = Object.freeze({
  NONE: 'none',
  SHARED: 'shared'
});

/**
 * @enum {string}
 */
var RootPath = Object.seal({
  DOWNLOADS: '/must-be-filled-in-test-setup',
  DRIVE: '/must-be-filled-in-test-setup',
});

/**
 * File system entry information for tests.
 *
 * @param {EntryType} type Entry type.
 * @param {string} sourceFileName Source file name that provides file contents.
 * @param {string} targetName Name of entry on the test file system.
 * @param {string} mimeType Mime type.
 * @param {SharedOption} sharedOption Shared option.
 * @param {string} lastModifiedTime Last modified time as a text to be shown in
 *     the last modified column.
 * @param {string} nameText File name to be shown in the name column.
 * @param {string} sizeText Size text to be shown in the size column.
 * @param {string} typeText Type name to be shown in the type column.
 * @constructor
 */
var TestEntryInfo = function(type,
                             sourceFileName,
                             targetPath,
                             mimeType,
                             sharedOption,
                             lastModifiedTime,
                             nameText,
                             sizeText,
                             typeText) {
  this.type = type;
  this.sourceFileName = sourceFileName || '';
  this.targetPath = targetPath;
  this.mimeType = mimeType || '';
  this.sharedOption = sharedOption;
  this.lastModifiedTime = lastModifiedTime;
  this.nameText = nameText;
  this.sizeText = sizeText;
  this.typeText = typeText;
  Object.freeze(this);
};

TestEntryInfo.getExpectedRows = function(entries) {
  return entries.map(function(entry) { return entry.getExpectedRow(); });
};

/**
 * Obtains a expected row contents of the file in the file list.
 */
TestEntryInfo.prototype.getExpectedRow = function() {
  return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
};

/**
 * Filesystem entries used by the test cases.
 * @type {Object.<string, TestEntryInfo>}
 * @const
 */
var ENTRIES = {
  hello: new TestEntryInfo(
      EntryType.FILE, 'text.txt', 'hello.txt',
      'text/plain', SharedOption.NONE, 'Sep 4, 1998 12:34 PM',
      'hello.txt', '51 bytes', 'Plain text'),

  world: new TestEntryInfo(
      EntryType.FILE, 'video.ogv', 'world.ogv',
      'text/plain', SharedOption.NONE, 'Jul 4, 2012 10:35 AM',
      'world.ogv', '59 KB', 'OGG video'),

  unsupported: new TestEntryInfo(
      EntryType.FILE, 'random.bin', 'unsupported.foo',
      'application/x-foo', SharedOption.NONE, 'Jul 4, 2012 10:36 AM',
      'unsupported.foo', '8 KB', 'FOO file'),

  desktop: new TestEntryInfo(
      EntryType.FILE, 'image.png', 'My Desktop Background.png',
      'text/plain', SharedOption.NONE, 'Jan 18, 2038 1:02 AM',
      'My Desktop Background.png', '272 bytes', 'PNG image'),

  beautiful: new TestEntryInfo(
      EntryType.FILE, 'music.ogg', 'Beautiful Song.ogg',
      'text/plain', SharedOption.NONE, 'Nov 12, 2086 12:00 PM',
      'Beautiful Song.ogg', '14 KB', 'OGG audio'),

  photos: new TestEntryInfo(
      EntryType.DIRECTORY, null, 'photos',
      null, SharedOption.NONE, 'Jan 1, 1980 11:59 PM',
      'photos', '--', 'Folder'),

  testDocument: new TestEntryInfo(
      EntryType.FILE, null, 'Test Document',
      'application/vnd.google-apps.document',
      SharedOption.NONE, 'Apr 10, 2013 4:20 PM',
      'Test Document.gdoc', '--', 'Google document'),

  testSharedDocument: new TestEntryInfo(
      EntryType.FILE, null, 'Test Shared Document',
      'application/vnd.google-apps.document',
      SharedOption.SHARED, 'Mar 20, 2013 10:40 PM',
      'Test Shared Document.gdoc', '--', 'Google document'),

  newlyAdded: new TestEntryInfo(
      EntryType.FILE, 'music.ogg', 'newly added file.ogg',
      'audio/ogg', SharedOption.NONE, 'Sep 4, 1998 12:00 AM',
      'newly added file.ogg', '14 KB', 'OGG audio'),

  directoryA: new TestEntryInfo(
      EntryType.DIRECTORY, null, 'A',
      null, SharedOption.NONE, 'Jan 1, 2000 1:00 AM',
      'A', '--', 'Folder'),

  directoryB: new TestEntryInfo(
      EntryType.DIRECTORY, null, 'A/B',
      null, SharedOption.NONE, 'Jan 1, 2000 1:00 AM',
      'B', '--', 'Folder'),

  directoryC: new TestEntryInfo(
      EntryType.DIRECTORY, null, 'A/B/C',
      null, SharedOption.NONE, 'Jan 1, 2000 1:00 AM',
      'C', '--', 'Folder')
};

/**
 * Basic entry set for the local volume.
 * @type {Array.<TestEntryInfo>}
 * @const
 */
var BASIC_LOCAL_ENTRY_SET = [
  ENTRIES.hello,
  ENTRIES.world,
  ENTRIES.desktop,
  ENTRIES.beautiful,
  ENTRIES.photos
];

/**
 * Basic entry set for the drive volume.
 *
 * TODO(hirono): Add a case for an entry cached by FileCache. For testing
 *               Drive, create more entries with Drive specific attributes.
 *
 * @type {Array.<TestEntryInfo>}
 * @const
 */
var BASIC_DRIVE_ENTRY_SET = [
  ENTRIES.hello,
  ENTRIES.world,
  ENTRIES.desktop,
  ENTRIES.beautiful,
  ENTRIES.photos,
  ENTRIES.unsupported,
  ENTRIES.testDocument,
  ENTRIES.testSharedDocument
];

var NESTED_ENTRY_SET = [
  ENTRIES.directoryA,
  ENTRIES.directoryB,
  ENTRIES.directoryC
];

/**
 * Expected files shown in "Recent". Directories (e.g. 'photos') are not in this
 * list as they are not expected in "Recent".
 *
 * @type {Array.<TestEntryInfo>}
 * @const
 */
var RECENT_ENTRY_SET = [
  ENTRIES.hello,
  ENTRIES.world,
  ENTRIES.desktop,
  ENTRIES.beautiful,
  ENTRIES.unsupported,
  ENTRIES.testDocument,
  ENTRIES.testSharedDocument
];

/**
 * Expected files shown in "Offline", which should have the files
 * "available offline". Google Documents, Google Spreadsheets, and the files
 * cached locally are "available offline".
 *
 * @type {Array.<TestEntryInfo>}
 * @const
 */
var OFFLINE_ENTRY_SET = [
  ENTRIES.testDocument,
  ENTRIES.testSharedDocument
];

/**
 * Expected files shown in "Shared with me", which should be the entries labeled
 * with "shared-with-me".
 *
 * @type {Array.<TestEntryInfo>}
 * @const
 */
var SHARED_WITH_ME_ENTRY_SET = [
  ENTRIES.testSharedDocument
];

/**
 * Opens a Files.app's main window.
 *
 * TODO(mtomasz): Pass a volumeId or an enum value instead of full paths.
 *
 * @param {Object} appState App state to be passed with on opening Files.app.
 *     Can be null.
 * @param {?string} initialRoot Root path to be used as a default current
 *     directory during initialization. Can be null, for no default path.
 * @param {function(string)} Callback with the app id.
 */
function openNewWindow(appState, initialRoot, callback) {
  var appId;

  // TODO(mtomasz): Migrate from full paths to a pair of a volumeId and a
  // relative path. To compose the URL communicate via messages with
  // file_manager_browser_test.cc.
  var processedAppState = appState || {};
  if (initialRoot) {
    processedAppState.currentDirectoryURL =
        'filesystem:chrome-extension://' + FILE_MANAGER_EXTENSIONS_ID +
        '/external' + initialRoot;
  }

  callRemoteTestUtil('openMainWindow', null, [processedAppState], callback);
}

/**
 * Opens a Files.app's main window and waits until it is initialized. Fills
 * the window with initial files. Should be called for the first window only.
 *
 * TODO(hirono): Add parameters to specify the entry set to be prepared.
 * TODO(mtomasz): Pass a volumeId or an enum value instead of full paths.
 *
 * @param {Object} appState App state to be passed with on opening Files.app.
 *     Can be null.
 * @param {?string} initialRoot Root path to be used as a default current
 *     directory during initialization. Can be null, for no default path.
 * @param {function(string, Array.<Array.<string>>)} Callback with the app id
 *     and with the file list.
 */
function setupAndWaitUntilReady(appState, initialRoot, callback) {
  var appId;

  StepsRunner.run([
    function() {
      openNewWindow(appState, initialRoot, this.next);
    },
    function(inAppId) {
      appId = inAppId;
      addEntries(['local'], BASIC_LOCAL_ENTRY_SET, this.next);
    },
    function(success) {
      chrome.test.assertTrue(success);
      addEntries(['drive'], BASIC_DRIVE_ENTRY_SET, this.next);
    },
    function(success) {
      chrome.test.assertTrue(success);
      callRemoteTestUtil('waitForFileListChange', appId, [0], this.next);
    },
    function(fileList) {
      callback(appId, fileList);
      this.next();
    }
  ]);
}

/**
 * Verifies if there are no Javascript errors in any of the app windows.
 * @param {function()} Completion callback.
 */
function checkIfNoErrorsOccured(callback) {
  callRemoteTestUtil('getErrorCount', null, [], function(count) {
    chrome.test.assertEq(0, count);
    callback();
  });
}

/**
 * Returns the name of the given file list entry.
 * @param {Array.<string>} file An entry in a file list.
 * @return {string} Name of the file.
 */
function getFileName(fileListEntry) {
  return fileListEntry[0];
}

/**
 * Returns the size of the given file list entry.
 * @param {Array.<string>} An entry in a file list.
 * @return {string} Size of the file.
 */
function getFileSize(fileListEntry) {
  return fileListEntry[1];
}

/**
 * Returns the type of the given file list entry.
 * @param {Array.<string>} An entry in a file list.
 * @return {string} Type of the file.
 */
function getFileType(fileListEntry) {
  return fileListEntry[2];
}

/**
 * Namespace for test cases.
 */
var testcase = {};

/**
 * Namespace for intermediate test cases.
 * */
testcase.intermediate = {};

/**
 * Tests if the files initially added by the C++ side are displayed, and
 * that a subsequently added file shows up.
 *
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.fileDisplay = function(path) {
  var appId;

  var expectedFilesBefore =
      TestEntryInfo.getExpectedRows(path == RootPath.DRIVE ?
          BASIC_DRIVE_ENTRY_SET : BASIC_LOCAL_ENTRY_SET).sort();

  var expectedFilesAfter =
      expectedFilesBefore.concat([ENTRIES.newlyAdded.getExpectedRow()]).sort();

  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Notify that the list has been verified and a new file can be added
    // in file_manager_browsertest.cc.
    function(inAppId, actualFilesBefore) {
      appId = inAppId;
      chrome.test.assertEq(expectedFilesBefore, actualFilesBefore);
      addEntries(['local', 'drive'], [ENTRIES.newlyAdded], this.next);
    },
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForFileListChange',
          appId,
          [expectedFilesBefore.length],
          this.next);
    },
    // Confirm the file list.
    function(actualFilesAfter) {
      chrome.test.assertEq(expectedFilesAfter, actualFilesAfter);
      checkIfNoErrorsOccured(this.next);
    },
  ]);
};

/**
 * Tests if the gallery shows up for the selected image and that the image
 * gets displayed.
 *
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.galleryOpen = function(path) {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Resize the window to desired dimensions to avoid flakyness.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('resizeWindow',
                         appId,
                         [320, 320],
                         this.next);
    },
    // Select the image.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('openFile',
                         appId,
                         ['My Desktop Background.png'],
                         this.next);
    },
    // Wait for the image in the gallery's screen image.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.gallery .content canvas.image',
                          'iframe.overlay-pane'],
                         this.next);
    },
    // Verify the gallery's screen image.
    function(element) {
      chrome.test.assertEq('320', element.attributes.width);
      chrome.test.assertEq('240', element.attributes.height);
      // Get the full-resolution image.
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.gallery .content canvas.fullres',
                          'iframe.overlay-pane'],
                         this.next);
    },
    // Verify the gallery's full resolution image.
    function(element) {
      chrome.test.assertEq('800', element.attributes.width);
      chrome.test.assertEq('600', element.attributes.height);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests if the audio player shows up for the selected image and that the audio
 * is loaded successfully.
 *
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.audioOpen = function(path) {
  var appId;
  var audioAppId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Select the song.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'openFile', appId, ['Beautiful Song.ogg'], this.next);
    },
    // Wait for the audio player.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForWindow',
                         null,
                         ['audio_player.html'],
                         this.next);
    },
    // Wait for the audio tag and verify the source.
    function(inAppId) {
      audioAppId = inAppId;
      callRemoteTestUtil('waitForElement',
                         audioAppId,
                         ['audio-player[playing]'],
                         this.next);
    },
    // Get the title tag.
    function(element) {
      chrome.test.assertEq(
          'filesystem:chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/' +
              'external' + path + '/Beautiful%20Song.ogg',
          element.attributes.currenttrackurl);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests if the video player shows up for the selected movie and that it is
 * loaded successfully.
 *
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.videoOpen = function(path) {
  var appId;
  var videoAppId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    function(inAppId) {
      appId = inAppId;
      // Select the song.
      callRemoteTestUtil(
          'openFile', appId, ['world.ogv'], this.next);
    },
    function(result) {
      chrome.test.assertTrue(result);
      // Wait for the video player.
      callRemoteTestUtil('waitForWindow',
                         null,
                         ['video_player.html'],
                         this.next);
    },
    function(inAppId) {
      videoAppId = inAppId;
      // Wait for the video tag and verify the source.
      callRemoteTestUtil('waitForElement',
                         videoAppId,
                         ['video[src]'],
                         this.next);
    },
    function(element) {
      chrome.test.assertEq(
          'filesystem:chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/' +
              'external' + path + '/world.ogv',
          element.attributes.src);
      // Wait for the window's inner dimensions. Should be changed to the video
      // size once the metadata is loaded.
      callRemoteTestUtil('waitForWindowGeometry',
                         videoAppId,
                         [320, 192],
                         this.next);
    },
    function(element) {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests copying a file to the same directory and waits until the file lists
 * changes.
 *
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.keyboardCopy = function(path, callback) {
  var filename = 'world.ogv';
  var expectedFilesBefore =
      TestEntryInfo.getExpectedRows(path == RootPath.DRIVE ?
          BASIC_DRIVE_ENTRY_SET : BASIC_LOCAL_ENTRY_SET).sort();
  var expectedFilesAfter =
      expectedFilesBefore.concat([['world (1).ogv', '59 KB', 'OGG video']]);

  var appId, fileListBefore;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Copy the file.
    function(inAppId, inFileListBefore) {
      appId = inAppId;
      fileListBefore = inFileListBefore;
      chrome.test.assertEq(expectedFilesBefore, inFileListBefore);
      callRemoteTestUtil('copyFile', appId, [filename], this.next);
    },
    // Wait for a file list change.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [expectedFilesAfter,
                          {ignoreLastModifiedTime: true}],
                         this.next);
    },
    // Verify the result.
    function(fileList) {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests deleting a file and and waits until the file lists changes.
 * @param {string} path Directory path to be tested.
 */
testcase.intermediate.keyboardDelete = function(path) {
  // Returns true if |fileList| contains |filename|.
  var isFilePresent = function(filename, fileList) {
    for (var i = 0; i < fileList.length; i++) {
      if (getFileName(fileList[i]) == filename)
        return true;
    }
    return false;
  };

  var filename = 'world.ogv';
  var directoryName = 'photos';
  var appId, fileListBefore;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Delete the file.
    function(inAppId, inFileListBefore) {
      appId = inAppId;
      fileListBefore = inFileListBefore;
      chrome.test.assertTrue(isFilePresent(filename, fileListBefore));
      callRemoteTestUtil(
          'deleteFile', appId, [filename], this.next);
    },
    // Reply to a dialog.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitAndAcceptDialog', appId, [], this.next);
    },
    // Wait for a file list change.
    function() {
      callRemoteTestUtil('waitForFileListChange',
                         appId,
                         [fileListBefore.length],
                         this.next);
    },
    // Delete the directory.
    function(fileList) {
      fileListBefore = fileList;
      chrome.test.assertFalse(isFilePresent(filename, fileList));
      chrome.test.assertTrue(isFilePresent(directoryName, fileList));
      callRemoteTestUtil('deleteFile', appId, [directoryName], this.next);
    },
    // Reply to a dialog.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitAndAcceptDialog', appId, [], this.next);
    },
    // Wait for a file list change.
    function() {
      callRemoteTestUtil('waitForFileListChange', appId,
                         [fileListBefore.length], this.next);
    },
    // Verify the result.
    function(fileList) {
      chrome.test.assertFalse(isFilePresent(directoryName, fileList));
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

testcase.fileDisplayDownloads = function() {
  testcase.intermediate.fileDisplay(RootPath.DOWNLOADS);
};

testcase.galleryOpenDownloads = function() {
  testcase.intermediate.galleryOpen(RootPath.DOWNLOADS);
};

testcase.audioOpenDownloads = function() {
  testcase.intermediate.audioOpen(RootPath.DOWNLOADS);
};

testcase.videoOpenDownloads = function() {
  testcase.intermediate.videoOpen(RootPath.DOWNLOADS);
};

testcase.keyboardCopyDownloads = function() {
  testcase.intermediate.keyboardCopy(RootPath.DOWNLOADS);
};

testcase.keyboardDeleteDownloads = function() {
  testcase.intermediate.keyboardDelete(RootPath.DOWNLOADS);
};

testcase.fileDisplayDrive = function() {
  testcase.intermediate.fileDisplay(RootPath.DRIVE);
};

testcase.galleryOpenDrive = function() {
  testcase.intermediate.galleryOpen(RootPath.DRIVE);
};

testcase.audioOpenDrive = function() {
  testcase.intermediate.audioOpen(RootPath.DRIVE);
};

testcase.videoOpenDrive = function() {
  testcase.intermediate.videoOpen(RootPath.DRIVE);
};

testcase.keyboardCopyDrive = function() {
  testcase.intermediate.keyboardCopy(RootPath.DRIVE);
};

testcase.keyboardDeleteDrive = function() {
  testcase.intermediate.keyboardDelete(RootPath.DRIVE);
};

/**
 * Tests opening the "Recent" on the sidebar navigation by clicking the icon,
 * and verifies the directory contents. We test if there are only files, since
 * directories are not allowed in "Recent". This test is only available for
 * Drive.
 */
testcase.openSidebarRecent = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Click the icon of the Recent volume.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
        'selectVolume', appId, ['drive_recent'], this.next);
    },
    // Wait until the file list is updated.
    function(result) {
      chrome.test.assertFalse(!result);
      callRemoteTestUtil(
          'waitForFileListChange',
          appId,
          [BASIC_DRIVE_ENTRY_SET.length],
          this.next);
    },
    // Verify the file list.
    function(actualFilesAfter) {
      chrome.test.assertEq(
          TestEntryInfo.getExpectedRows(RECENT_ENTRY_SET).sort(),
          actualFilesAfter);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests opening the "Offline" on the sidebar navigation by clicking the icon,
 * and checks contenets of the file list. Only the entries "available offline"
 * should be shown. "Available offline" entires are hosted documents and the
 * entries cached by DriveCache.
 */
testcase.openSidebarOffline = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Click the icon of the Offline volume.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
        'selectVolume', appId, ['drive_offline'], this.next);
    },
    // Wait until the file list is updated.
    function(result) {
      chrome.test.assertFalse(!result);
      callRemoteTestUtil(
          'waitForFileListChange',
          appId,
          [BASIC_DRIVE_ENTRY_SET.length],
          this.next);
    },
    // Verify the file list.
    function(actualFilesAfter) {
      chrome.test.assertEq(
          TestEntryInfo.getExpectedRows(OFFLINE_ENTRY_SET).sort(),
          actualFilesAfter);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests opening the "Shared with me" on the sidebar navigation by clicking the
 * icon, and checks contents of the file list. Only the entries labeled with
 * "shared-with-me" should be shown.
 */
testcase.openSidebarSharedWithMe = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Click the icon of the Shared With Me volume.
    function(inAppId) {
      appId = inAppId;
      // Use the icon for a click target.
      callRemoteTestUtil('selectVolume',
                         appId,
                         ['drive_shared_with_me'], this.next);
    },
    // Wait until the file list is updated.
    function(result) {
      chrome.test.assertFalse(!result);
      callRemoteTestUtil(
          'waitForFileListChange',
          appId,
          [BASIC_DRIVE_ENTRY_SET.length],
          this.next);
    },
    // Verify the file list.
    function(actualFilesAfter) {
      chrome.test.assertEq(
          TestEntryInfo.getExpectedRows(SHARED_WITH_ME_ENTRY_SET).sort(),
          actualFilesAfter);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests autocomplete with a query 'hello'. This test is only available for
 * Drive.
 */
testcase.autocomplete = function() {
  var EXPECTED_AUTOCOMPLETE_LIST = [
    '\'hello\' - search Drive\n',
    'hello.txt\n',
  ];

  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Perform an auto complete test and wait until the list changes.
    // TODO(mtomasz): Move the operation from test_util.js to tests_cases.js.
    function(appId, list) {
      callRemoteTestUtil('performAutocompleteAndWait',
                         appId,
                         ['hello', EXPECTED_AUTOCOMPLETE_LIST.length],
                         this.next);
    },
    // Verify the list contents.
    function(autocompleteList) {
      chrome.test.assertEq(EXPECTED_AUTOCOMPLETE_LIST, autocompleteList);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Test function to copy from the specified source to the specified destination.
 * @param {string} targetFile Name of target file to be copied.
 * @param {string} srcName Type of source volume. e.g. downloads, drive,
 *     drive_recent, drive_shared_with_me, drive_offline.
 * @param {Array.<TestEntryInfo>} srcEntries Expected initial contents in the
 *     source volume.
 * @param {string} dstName Type of destination volume.
 * @param {Array.<TestEntryInfo>} dstEntries Expected initial contents in the
 *     destination volume.
 */
testcase.intermediate.copyBetweenVolumes = function(targetFile,
                                                    srcName,
                                                    srcEntries,
                                                    dstName,
                                                    dstEntries) {
  var srcContents = TestEntryInfo.getExpectedRows(srcEntries).sort();
  var dstContents = TestEntryInfo.getExpectedRows(dstEntries).sort();

  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Select the source volume.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'selectVolume', appId, [srcName], this.next);
    },
    // Wait for the expected files to appear in the file list.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForFiles', appId, [srcContents], this.next);
    },
    // Select the source file.
    function() {
      callRemoteTestUtil(
          'selectFile', appId, [targetFile], this.next);
    },
    // Copy the file.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('execCommand', appId, ['copy'], this.next);
    },
    // Select the destination volume.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'selectVolume', appId, [dstName], this.next);
    },
    // Wait for the expected files to appear in the file list.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForFiles', appId, [dstContents], this.next);
    },
    // Paste the file.
    function() {
      callRemoteTestUtil(
          'execCommand', appId, ['paste'], this.next);
    },
    // Wait for the file list to change.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForFileListChange',
                         appId,
                         [dstContents.length],
                         this.next);
    },
    // Check the last contents of file list.
    function(actualFilesAfter) {
      chrome.test.assertEq(dstContents.length + 1,
                           actualFilesAfter.length);
      var copiedItem = null;
      for (var i = 0; i < srcContents.length; i++) {
        if (srcContents[i][0] == targetFile) {
          copiedItem = srcContents[i];
          break;
        }
      }
      chrome.test.assertTrue(copiedItem != null);
      for (var i = 0; i < dstContents.length; i++) {
        if (dstContents[i][0] == targetFile) {
          // Replace the last '.' in filename with ' (1).'.
          // e.g. 'my.note.txt' -> 'my.note (1).txt'
          copiedItem[0] = copiedItem[0].replace(/\.(?=[^\.]+$)/, ' (1).');
          break;
        }
      }
      // File size can not be obtained on drive_shared_with_me volume and
      // drive_offline.
      var ignoreSize = srcName == 'drive_shared_with_me' ||
                       dstName == 'drive_shared_with_me' ||
                       srcName == 'drive_offline' ||
                       dstName == 'drive_offline';
      for (var i = 0; i < actualFilesAfter.length; i++) {
        if (actualFilesAfter[i][0] == copiedItem[0] &&
            (ignoreSize || actualFilesAfter[i][1] == copiedItem[1]) &&
            actualFilesAfter[i][2] == copiedItem[2]) {
          checkIfNoErrorsOccured(this.next);
          return;
        }
      }
      chrome.test.fail();
    }
  ]);
};

/**
 * Test sharing dialog for a file or directory on Drive
 * @param {string} path Path for a file or a directory to be shared.
 */
testcase.intermediate.share = function(path) {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Select the source file.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'selectFile', appId, [path], this.next);
    },
    // Wait for the share button.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['#share-button:not([disabled])'],
                         this.next);
    },
    // Invoke the share dialog.
    function(result) {
      callRemoteTestUtil('fakeMouseClick',
                         appId,
                         ['#share-button'],
                         this.next);
    },
    // Wait until the share dialog's contents are shown.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.share-dialog-webview-wrapper.loaded'],
                         this.next);
    },
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil('waitForStyles',
                         appId,
                         [{
                            query: '.share-dialog-webview-wrapper.loaded',
                            styles: {
                              width: '350px',
                              height: '250px'
                            }
                          }],
                         this.next);
    },
    // Wait until the share dialog's contents are shown.
    function(result) {
      callRemoteTestUtil('executeScriptInWebView',
                         appId,
                         ['.share-dialog-webview-wrapper.loaded webview',
                          'document.querySelector("button").click()'],
                         this.next);
    },
    // Wait until the share dialog's contents are hidden.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.share-dialog-webview-wrapper.loaded',
                          null,   // iframeQuery
                          true],  // inverse
                         this.next);
    },
    // Check for Javascript errros.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Test utility for traverse tests.
 * @param {string} path Root path to be traversed.
 */
testcase.intermediate.traverseDirectories = function(path) {
  var appId;
  StepsRunner.run([
    // Set up File Manager. Do not add initial files.
    function() {
      openNewWindow(null, path, this.next);
    },
    // Check the initial view.
    function(inAppId) {
      appId = inAppId;
      addEntries(['local', 'drive'], NESTED_ENTRY_SET, this.next);
    },
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [[ENTRIES.directoryA.getExpectedRow()]],
                         this.next);
    },
    // Open the directory
    function() {
      callRemoteTestUtil('openFile', appId, ['A'], this.next);
    },
    // Check the contents of current directory.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [[ENTRIES.directoryB.getExpectedRow()]],
                         this.next);
    },
    // Open the directory
    function() {
      callRemoteTestUtil('openFile', appId, ['B'], this.next);
    },
    // Check the contents of current directory.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [[ENTRIES.directoryC.getExpectedRow()]],
                         this.next);
    },
    // Check the error.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests copy from drive's root to local's downloads.
 */
testcase.transferFromDriveToDownloads = function() {
  testcase.intermediate.copyBetweenVolumes('hello.txt',
                                           'drive',
                                           BASIC_DRIVE_ENTRY_SET,
                                           'downloads',
                                           BASIC_LOCAL_ENTRY_SET);
};

/**
 * Tests copy from local's downloads to drive's root.
 */
testcase.transferFromDownloadsToDrive = function() {
  testcase.intermediate.copyBetweenVolumes('hello.txt',
                                           'downloads',
                                           BASIC_LOCAL_ENTRY_SET,
                                           'drive',
                                           BASIC_DRIVE_ENTRY_SET);
};

/**
 * Tests copy from drive's shared_with_me to local's downloads.
 */
testcase.transferFromSharedToDownloads = function() {
  testcase.intermediate.copyBetweenVolumes('Test Shared Document.gdoc',
                                           'drive_shared_with_me',
                                           SHARED_WITH_ME_ENTRY_SET,
                                           'downloads',
                                           BASIC_LOCAL_ENTRY_SET);
};

/**
 * Tests copy from drive's shared_with_me to drive's root.
 */
testcase.transferFromSharedToDrive = function() {
  testcase.intermediate.copyBetweenVolumes('Test Shared Document.gdoc',
                                           'drive_shared_with_me',
                                           SHARED_WITH_ME_ENTRY_SET,
                                           'drive',
                                           BASIC_DRIVE_ENTRY_SET);
};

/**
 * Tests copy from drive's recent to local's downloads.
 */
testcase.transferFromRecentToDownloads = function() {
  testcase.intermediate.copyBetweenVolumes('hello.txt',
                                           'drive_recent',
                                           RECENT_ENTRY_SET,
                                           'downloads',
                                           BASIC_LOCAL_ENTRY_SET);
};

/**
 * Tests copy from drive's recent to drive's root.
 */
testcase.transferFromRecentToDrive = function() {
  testcase.intermediate.copyBetweenVolumes('hello.txt',
                                           'drive_recent',
                                           RECENT_ENTRY_SET,
                                           'drive',
                                           BASIC_DRIVE_ENTRY_SET);
};

/**
 * Tests copy from drive's offline to local's downloads.
 */
testcase.transferFromOfflineToDownloads = function() {
  testcase.intermediate.copyBetweenVolumes('Test Document.gdoc',
                                           'drive_offline',
                                           OFFLINE_ENTRY_SET,
                                           'downloads',
                                           BASIC_LOCAL_ENTRY_SET);
};

/**
 * Tests copy from drive's offline to drive's root.
 */
testcase.transferFromOfflineToDrive = function() {
  testcase.intermediate.copyBetweenVolumes('Test Document.gdoc',
                                           'drive_offline',
                                           OFFLINE_ENTRY_SET,
                                           'drive',
                                           BASIC_DRIVE_ENTRY_SET);
};

/**
 * Tests sharing a file on Drive
 */
testcase.shareFile = function() {
  testcase.intermediate.share('world.ogv');
};

/**
 * Tests sharing a directory on Drive
 */
testcase.shareDirectory = function() {
  testcase.intermediate.share('photos');
};

testcase.executeDefaultTaskOnDrive = function(root) {
  testcase.intermediate.executeDefaultTask(true);
};

testcase.executeDefaultTaskOnDownloads = function(root) {
  testcase.intermediate.executeDefaultTask(false);
};

/**
 * Tests executing the default task when there is only one task.
 * @param {boolean} drive Whether to test Drive or Downloads.
 */
testcase.intermediate.executeDefaultTask = function(drive) {
  var path = drive ? RootPath.DRIVE : RootPath.DOWNLOADS;
  var taskId = drive ? 'dummytaskid|drive|open-with' : 'dummytaskid|open-with'
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, path, this.next);
    },
    // Override tasks list with a dummy task.
    function(inAppId, inFileListBefore) {
      appId = inAppId;

      callRemoteTestUtil(
          'overrideTasks',
          appId,
          [[
            {
              driveApp: false,
              iconUrl: 'chrome://theme/IDR_DEFAULT_FAVICON',  // Dummy icon
              isDefault: true,
              taskId: taskId,
              title: 'The dummy task for test'
            }
          ]],
          this.next);
    },
    // Select file.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'selectFile', appId, ['hello.txt'], this.next);
    },
    // Double-click the file.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'fakeMouseDoubleClick',
          appId,
          ['#file-list li.table-row[selected] .filename-label span'],
          this.next);
    },
    // Wait until the task is executed.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'waitUntilTaskExecutes',
          appId,
          [taskId],
          this.next);
    },
    // Check the error.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests sharing a file on Drive
 */
testcase.suggestAppDialog = function() {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      chrome.test.sendMessage(
          JSON.stringify({name: 'getCwsWidgetContainerMockUrl'}),
          this.next);
    },
    // Override the container URL with the mock.
    function(json) {
      var data = JSON.parse(json);

      var appState = {
        suggestAppsDialogState: {
          overrideCwsContainerUrlForTest: data.url,
          overrideCwsContainerOriginForTest: data.origin
        }
      };
      setupAndWaitUntilReady(appState, RootPath.DRIVE, this.next);
    },
    function(inAppId, inFileListBefore) {
      appId = inAppId;

      callRemoteTestUtil(
          'selectFile', appId, ['unsupported.foo'], this.next);
    },
    // Double-click the file.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'fakeMouseDoubleClick',
          appId,
          ['#file-list li.table-row[selected] .filename-label span'],
          this.next);
    },
    // Wait for the widget is loaded.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#suggest-app-dialog webview[src]'],
          this.next);
    },
    // Wait for the widget is initialized.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#suggest-app-dialog:not(.show-spinner)'],
          this.next);
    },
    // Override task APIs for test.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'overrideTasks',
          appId,
          [[
            {
              driveApp: false,
              iconUrl: 'chrome://theme/IDR_DEFAULT_FAVICON',  // Dummy icon
              isDefault: true,
              taskId: 'dummytaskid|drive|open-with',
              title: 'The dummy task for test'
            }
          ]],
          this.next);
    },
    // Override installWebstoreItem API for test.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'overrideInstallWebstoreItemApi',
          appId,
          [
            'DUMMY_ITEM_ID_FOR_TEST',  // Same ID in cws_container_mock/main.js.
            null  // Success
          ],
          this.next);
    },
    // Initiate an installation from the widget.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'executeScriptInWebView',
          appId,
          ['#suggest-app-dialog webview',
           'document.querySelector("button").click()'],
          this.next);
    },
    // Wait until the installation is finished and the dialog is closed.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['#suggest-app-dialog',
                          null,   // iframeQuery
                          true],  // inverse
                         this.next);
    },
    // Wait until the task is executed.
    function(result) {
      chrome.test.assertTrue(!!result);
      callRemoteTestUtil(
          'waitUntilTaskExecutes',
          appId,
          ['dummytaskid|drive|open-with'],
          this.next);
    },
    // Check error
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests hiding the search box.
 */
testcase.hideSearchBox = function() {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Resize the window.
    function(inAppId, inFileListBefore) {
      appId = inAppId;
      callRemoteTestUtil('resizeWindow', appId, [100, 100], this.next);
    },
    // Wait for the style change.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForStyles',
                         appId,
                         [{
                            query: '#search-box',
                            styles: {visibility: 'hidden'}
                          }],
                         this.next);
    },
    // Check the styles
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests restoring the sorting order.
 */
testcase.restoreSortColumn = function() {
  var appId;
  var EXPECTED_FILES = TestEntryInfo.getExpectedRows([
    ENTRIES.world,
    ENTRIES.photos,
    ENTRIES.desktop,
    ENTRIES.hello,
    ENTRIES.beautiful
  ]);
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Sort by name.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('fakeMouseClick',
                         appId,
                         ['.table-header-cell:nth-of-type(1)'],
                         this.next);
    },
    // Check the sorted style of the header.
    function() {
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.table-header-sort-image-asc'],
                         this.next);
    },
    // Sort by name.
    function() {
      callRemoteTestUtil('fakeMouseClick',
                         appId,
                         ['.table-header-cell:nth-of-type(1)'],
                         this.next);
    },
    // Check the sorted style of the header.
    function() {
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.table-header-sort-image-desc'],
                         this.next);
    },
    // Check the sorted files.
    function() {
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [EXPECTED_FILES, {orderCheck: true}],
                         this.next);
    },
    // Open another window, where the sorted column should be restored.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Check the sorted style of the header.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.table-header-sort-image-desc'],
                         this.next);
    },
    // Check the sorted files.
    function() {
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [EXPECTED_FILES, {orderCheck: true}],
                         this.next);
    },
    // Check the error.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests restoring the current view (the file list or the thumbnail grid).
 */
testcase.restoreCurrentView = function() {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Check the initial view.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.thumbnail-grid[hidden]'],
                         this.next);
    },
    // Opens the gear menu.
    function() {
      callRemoteTestUtil('fakeMouseClick',
                         appId,
                         ['#gear-button'],
                         this.next);
    },
    // Change the current view.
    function() {
      callRemoteTestUtil('fakeMouseClick',
                         appId,
                         ['#thumbnail-view'],
                         this.next);
    },
    // Check the new current view.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.detail-table[hidden]'],
                         this.next);
    },
    // Open another window, where the current view is restored.
    function() {
      openNewWindow(null, RootPath.DOWNLOADS, this.next);
    },
    // Check the current view.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.detail-table[hidden]'],
                         this.next);
    },
    // Check the error.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests keyboard operations of the navigation list.
 */
testcase.traverseNavigationList = function() {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Wait until Google Drive is selected.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#navigation-list > .root-item > ' +
               '.volume-icon[volume-type-icon="drive"]'],
          this.next);
    },
    // Ensure that the current directory is changed to Google Drive.
    function() {
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [TestEntryInfo.getExpectedRows(BASIC_DRIVE_ENTRY_SET),
                          {ignoreLastModifiedTime: true}],
                         this.next);
    },
    // Press the UP key.
    function() {
      callRemoteTestUtil('fakeKeyDown',
                         appId,
                         ['#navigation-list', 'Up', true],
                         this.next);
    },
    // Ensure that Gogole Drive is selected since it is the first item.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#navigation-list > .root-item > ' +
               '.volume-icon[volume-type-icon="drive"]'],
          this.next);
    },
    // Press the DOWN key.
    function() {
      callRemoteTestUtil('fakeKeyDown',
                         appId,
                         ['#navigation-list', 'Down', true],
                         this.next);
    },
    // Ensure that Downloads is selected.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#navigation-list > .root-item > ' +
               '.volume-icon[volume-type-icon="downloads"]'],
          this.next);
    },
    // Ensure that the current directory is changed to Downloads.
    function() {
      callRemoteTestUtil('waitForFiles',
                         appId,
                         [TestEntryInfo.getExpectedRows(BASIC_LOCAL_ENTRY_SET),
                          {ignoreLastModifiedTime: true}],
                         this.next);
    },
    // Press the DOWN key again.
    function() {
      callRemoteTestUtil('fakeKeyDown',
                         appId,
                         ['#navigation-list', 'Down', true],
                         this.next);
    },
    // Ensure that Downloads is still selected since it is the last item.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement',
          appId,
          ['#navigation-list > .root-item > ' +
               '.volume-icon[volume-type-icon="downloads"]'],
          this.next);
    },
    // Check for errors.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests restoring geometry of the Files app.
 */
testcase.restoreGeometry = function() {
  var appId;
  var appId2;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Resize the window to minimal dimensions.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'resizeWindow', appId, [640, 480], this.next);
    },
    // Check the current window's size.
    function(inAppId) {
      callRemoteTestUtil('waitForWindowGeometry',
                         appId,
                         [640, 480],
                         this.next);
    },
    // Enlarge the window by 10 pixels.
    function(result) {
      callRemoteTestUtil(
          'resizeWindow', appId, [650, 490], this.next);
    },
    // Check the current window's size.
    function() {
      callRemoteTestUtil('waitForWindowGeometry',
                         appId,
                         [650, 490],
                         this.next);
    },
    // Open another window, where the current view is restored.
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Check the next window's size.
    function(inAppId) {
      appId2 = inAppId;
      callRemoteTestUtil('waitForWindowGeometry',
                         appId2,
                         [650, 490],
                         this.next);
    },
    // Check for errors.
    function() {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests to traverse local directories.
 */
testcase.traverseDownloads =
    testcase.intermediate.traverseDirectories.bind(null, RootPath.DOWNLOADS);

/**
 * Tests to traverse drive directories.
 */
testcase.traverseDrive =
    testcase.intermediate.traverseDirectories.bind(null, RootPath.DRIVE);

/**
 * Tests the focus behavior of the search box.
 */
testcase.searchBoxFocus = function() {
  var appId;
  StepsRunner.run([
    // Set up File Manager.
    function() {
      setupAndWaitUntilReady(null, RootPath.DRIVE, this.next);
    },
    // Check that the file list has the focus on launch.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil(
          'waitForElement', appId, ['#file-list:focus'], this.next);
    },
    // Press the Ctrl-F key.
    function(element) {
      callRemoteTestUtil('fakeKeyDown',
                         appId,
                         ['body', 'U+0046', true],
                         this.next);
    },
    // Check that the search box has the focus.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement', appId, ['#search-box input:focus'], this.next);
    },
    // Press the Tab key.
    function(element) {
      callRemoteTestUtil('fakeKeyDown',
                         appId,
                         ['body', 'U+0009', false],
                         this.next);
    },
    // Check that the file list has the focus.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil(
          'waitForElement', appId, ['#file-list:focus'], this.next);
    },
    // Check for errors.
    function(element) {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

/**
 * Tests if a thumbnail for the selected item shows up in the preview panel.
 * This thumbnail is fetched via the image loader.
 */
testcase.thumbnailsDownloads = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Select the image.
    function(inAppId) {
      appId = inAppId;
      callRemoteTestUtil('selectFile',
                         appId,
                         ['My Desktop Background.png'],
                         this.next);
    },
    // Wait until the thumbnail shows up.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['.preview-thumbnails .img-container img'],
                         this.next);
    },
    // Verify the thumbnail.
    function(element) {
      chrome.test.assertTrue(element.attributes.src.indexOf(
          'data:image/jpeg') === 0);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

testcase.multiProfileBadge = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Add all users.
    function(inAppId) {
      appId = inAppId;
      chrome.test.sendMessage(JSON.stringify({name: 'addAllUsers'}),
                              this.next);
    },
    // Get the badge element.
    function(json) {
      chrome.test.assertTrue(JSON.parse(json));
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['#profile-badge'],
                         this.next);
    },
    // Verify no badge image is shown yet.  Move to other deskop.
    function(element) {
      chrome.test.assertTrue(!element.attributes.src, 'Badge hidden initially');
      callRemoteTestUtil('visitDesktop',
                         appId,
                         ['bob@invalid.domain'],
                         this.next);
    },
    // Get the badge element again.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['#profile-badge[src]'],
                         this.next);
    },
    // Verify an image source is filled. Go back to the original desktop
    function(element) {
      chrome.test.assertTrue(element.attributes.src.indexOf('data:image') === 0,
                             'Badge shown after moving desktop');
      callRemoteTestUtil('visitDesktop',
                         appId,
                         ['alice@invalid.domain'],
                         this.next);
    },
    // Wait for #profile-badge element with .src to disappear.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForElement',
                         appId,
                         ['#profile-badge[src]', null, true],
                         this.next);
    },
    // The image is gone.
    function(result) {
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

testcase.multiProfileVisitDesktopMenu = function() {
  var appId;
  StepsRunner.run([
    function() {
      setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
    },
    // Add all users.
    function(inAppId) {
      appId = inAppId;
      chrome.test.sendMessage(JSON.stringify({name: 'addAllUsers'}),
                              this.next);
    },
    // Wait for menu items. Profiles for non-current desktop should appear and
    // the profile for the current desktop (alice) should be hidden.
    function(json) {
      chrome.test.assertTrue(JSON.parse(json));
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['bob@invalid.domain', true],
                         this.next);
    },
    function() {
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['charlie@invalid.domain', true],
                         this.next);
    },
    function() {
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['alice@invalid.domain', false],
                         this.next);
    },
    // Activate the visit desktop menu.
    function() {
      callRemoteTestUtil('runVisitDesktopMenu',
                         appId,
                         ['bob@invalid.domain'],
                         this.next);
    },
    // Wait for the new menu state. Now 'alice' is shown and 'bob' is hidden.
    function(result) {
      chrome.test.assertTrue(result);
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['alice@invalid.domain', true],
                         this.next);
    },
    function() {
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['charlie@invalid.domain', true],
                         this.next);
    },
    function() {
      callRemoteTestUtil('waitForVisitDesktopMenu',
                         appId,
                         ['bob@invalid.domain', false],
                         this.next);
    },
    // Check that the window owner has indeed been changed.
    function() {
      chrome.test.sendMessage(JSON.stringify({name: 'getWindowOwnerId'}),
                              this.next);
    },
    function(result) {
      chrome.test.assertEq('bob@invalid.domain', result);
      checkIfNoErrorsOccured(this.next);
    }
  ]);
};

redpajama_set_name: RedPajamaGithub


Tania Tetlow, J.D. '95, is the president of Loyola University New Orleans. She not only leads the University, but also the development of knowledge and the pursuit of learning. She is assisted by Chief of Staff Lesli D. Harris.
Connect with the leadership and administrative offices that form the foundation of Loyola University.
The Office of Academic Affairs is responsible for strategic planning, administration, and evaluation of academics.
The Office of Institutional Advancement is in charge of alumni engagement, development, as well as stewardship and donor services.
The Office of Enrollment Management initiates and implements strategies and tactics to shape Loyola's enrollment.
The Office of Finance and Administration provides quality support services to students, faculty, and staff.
The Office of Mission+ Identity fosters the university's Jesuit and Catholic mission and identity.
The Board of Trustees are responsible for policy and sound management of our campus.


text:
Trump is 'ripping page out of Nixon playbook': Presidential historian Michael Beschloss explains what you should expect next
Presidential historian Michael Beschloss cautioned that President Donald Trump is ripping a page right out of the Richard Nixon playbook when it comes to wanting to fire special prosecutor Robert Mueller.
According to a New York Times report Thursday, Trump wanted to fire Robert Mueller, and that White House special counsel Don McGahn instructed him not to. The discussion between the two became so heated that McGahn threatened to resign if Mueller was terminated.
Bechloss said that Trump attacking the investigators for a partisan bent is part of a Nixonian pattern.
"In retrospect, what we know, is that [Nixon] was afraid that Cox was about to get the White House tapes — which we now know show that Richard Nixon was guilty of impeachable offenses."
Bechloss then connected the same kind of dots to Trump's objection to Mueller.
"We've got to be very much on alert about that tonight," he warned.
Watch the discussion below:
Former White House counsel for Richard Nixon, John Dean, explained that the legal brief out of President Donald Trump's White House was so bad that it had to have been dictated by Trump himself.
Saturday evening, Trump's legal team, chaired by Trump lawyer Jay Sekulow and White House counsel Pat Cipollone, filed their own form of a legal brief that responded to the case filed by Democrats ahead of Tuesday's impeachment trial.
The document called the proceedings "constitutionally invalid" and claims House Democrats are staging a "dangerous attack" with a "brazen and unlawful attempt to overturn the results of the 2016 election and interfere with the 2020 election."
Prince Harry posted a video from an HIV/AIDS fundraiser his mother once supported, where he explained his methodology for leaving his profile role as a royal.
"I will continue to be the same man who holds his country dear," said Harry.
He went on to say that he doesn't intend to walk away and he certainly won't walk away from his causes and interests. "We intend to live a life of service."
In the speech, he thanked those who took him under their wing in the absence of his mother
"I hope you can understand that it's what it had come to," he said for why their family intends to step back.


1. Despite 85.5% of respondents stating that obesity management was essential to primary care, only 21.4% felt competent in their obesity intervention skills.
2. Overall, primary care providers (PCPs) desired more training and noted their lack of ability with respect to dietary counseling.
Study Rundown: While PCPs are in a unique position to offer guidance and follow-up on weight management, there has been little international research investigating the factors involved in obesity counseling. The first of its kind to examine international obesity counseling practices and perceptions, this study used a self-report questionnaire to gather information from 1119 PCPs in France, Italy, Ukraine, and Poland. The survey measured responses to questions regarding perceptions of PCP role in obesity management, the frequency of weight, height and BMI tracking, availability of weight management programs, and physicians comfort with several aspects of obesity management. Results showed that PCPs vary in their opinions of the importance of obesity management in primary care practice, have low confidence in their dietary management skills, and indicate a desire to be trained. Limitations to the study include low response rate, reliance on self-reporting, and selection bias. The results display international differences between perceived important for PCPs to manage obesity in daily practice, their perceived abilities in dietary counseling, and may indicate a potential avenue to target the obesity epidemic through advanced clinician training in dietary management.
In-Depth [cross-sectional survey]: A 26-item, self-administered questionnaire was offered to 3464 PCPs, including family medicine and pediatric physicians, in Ukraine, Poland, France, and Italy. 1119 (32.4%) responded. There were significant differences in gender and specialty of respondents between nations. Overall, 85.5% of PCPs felt that obesity was relevant to primary care, though there were significant differences between the four countries surveyed, with 100% of Italian physicians believing it be relevant compared to 94.2% of French PCPs, 87.6% of Polish PCPs, and 60.3% of those from Ukraine (p<.0001). In total 21.4% of respondents felt competent in obesity management. 56.1% of PCPs surveyed felt comfortable with the dietary management of obesity. 61.7% wanted to receive advanced training in dietary management. Other significant differences between countries included the availability of weight-management programs, rates of regular height, weight and BMI measurements and plotting, and rates of referral for obesity.


text:
Pakistan's November CPI expected to decline marginally: finance ministry
In its monthly outlook, ministry says inflationary pressure was expected to ease marginally month-on-month due to smooth domestic supplies, unchanged energy prices in November and a stable exchange rate
Reuters Published November 29, 2022
ISLAMABAD: Pakistan's November CPI is expected to decline marginally and may remain in the range of 23%-25%, the country's finance ministry said in its monthly outlook on Tuesday.
The South Asian country's expenditure grew 26% in the first quarter of the financial year, the ministry said, adding that its fiscal deficit reached 1% of GDP in the same period.
CPI-based inflation jumps in October, clocks in at 26.6%
The outlook said inflationary pressure was expected to ease marginally month-on-month due to smooth domestic supplies, unchanged energy prices in November and a stable exchange rate.
It said the current account deficit declined to $2.8 billion in the first quarter of the current fiscal year, against $5.3 billion in the same period last year.
Ishaq Dar says Pakistani delegation to leave for Russia for potential oil deal
The South Asian nation faces a huge economic challenge in the face of devastating floods, which are estimated to have caused more than $30 billion in losses.
The International Monetary Fund (IMF) wants Pakistan to cut expenditure as it conducts the ninth review of a $7 billion bailout programme.
Pakistan and the IMF both have said this week that they have started online talks on the review.
The IMF in August approved the seventh and eights reviews of the bailout programme - agreed in 2019 - to allow the release of more than $1.1 billion.
Pakistan does not face any risk of default, reiterates Ishaq Dar
The ninth review has been pending since September.
The lender has said the finalisation of a floods recovery plan was essential to support discussions and continued financial support from multilateral and bilateral partners.
Pakistan secured a $6 billion bailout in 2019, which was topped up with another $1 billion earlier this year.
Pakistan inflation Ishaq Dar CPI IMF and Pakistan Finance minister Ishaq Dar


I am working on a new Proliant ML110 G7 server. The front fan is running at full speed and is putting out too much noise. I have done the following so far.
I cannot seem to isolate why it is not slowing down, since there are no options for controlling the fan.
Am I missing something, or could it be a defective server?
I do not have a redundant power supply (there is room for a second PSU) and was not intending to purchase one. I'm curious if this is the cause of the increased fan speed as I've seen other servers that spin up the fans when you remove a redundant PSU while the unit is on.
iLO3 was updated to 1.26 which made no change. Currently downloading the entire "HP Service Pack for ProLiant" so will see if that makes any change once applied.
I'm starting to think that this is how they are currently shipping G7's.
After a visit from a HP tech, my new ML110 G7 server is now whisper quiet. The front fan was the culprit.
All HP diagnostics reported green, yet the fan continued to run at around 50%. Re-seating the front fan resulted in it spinning down from 50% to around 10%.
I'm guessing that it may become dislodged during shipping so it's a good result.
I am currently having the same issue, stange since it is one year since reporting the original incident, and re-seating the fan(s) did not resolve. Any additional assistance is appriciated.


HAMMOND, Ind. — A statewide Silver Alert has been declared for a missing 81-year-old from Hammond.
Romulo Najera, 81, is described as 5 feet 7 inches tall, weighing 190 pounds, with gray hair and brown eyes. He was last wearing a camouflage hat, white button up shirt, blue jeans and black shoes.
Najera was last seen around 9 a.m. on Christmas morning.
Anyone with information on the whereabouts of Najera is asked to call Hammond police at 219-660-0000 or 911.


text:
Hands on Impressions with Nintendo's Fall 2013 Line-Up
News 10/8/2013 at 6:22 PM by Christopher Metz 0
Checking out their upcoming titles, all in a sweet trailer of nostalgia.
As with Microsoft's tour of the US, Nintendo is also stopping around the country to promote their line of Wii U and 3DS titles. Last Thursday, we scheduled a meet-up with them to discuss some of their upcoming co-op games and get a crack at them ourselves.
Our trip out to the outskirts of Philadelphia, PA proved to be quite valuable in getting a better idea of what sort of co-op content is coming out of Nintendo. Along with the main games we're be keeping an eye out for, like Super Mario 3D World, Donkey Kong Country: Tropical Freeze, and Sonic Lost World, other titles like Pikmin 3, The Legend of Zelda: A Link Between Worlds, and Wii Fit U quickly grabbed our attention. We also had the pleasure of trying out the upcoming 2DS handheld for ourselves.
After about 2 months since Pikmin 3 was released on Wii U, Nintendo recently began to roll out their planned DLC's for the months ahead. The "Collect Treasure Pack" recently arrived on the eShop, adding a total four new challenges to the "Collect Treasure!" co-op Mission Mode, as well as a free challenge to play regardless. The representative reiterated that even more DLC's are currently in the works to be released, though no official date was specified on them right now. The possibilities for all the DLC content, however, are still up in the air, so who knows what other co-op ideas might come Nintendo. From day one of playing Pikmin 3, I had high hopes that a co-op mode will be added to the Story Mode at some point, so I thought to ask if they could comment on that aspect. Unfortunately, they were comment on that. Still, I gave it a try for all our Pikmin fans out there.
We also got a hands-on look at the upcoming Nintendo 2DS handheld device, all while playing the second of the Legend of Zelda titles to hit this year: A Link Between Worlds. From my experience owning a 3DS XL, I can safely say that this new addition to the DS family is a pretty decent one; though we were skeptical at first. The build of it fit snug in the palms of my hand, with my fingertips easily reaching the enlarged L and R buttons very comfortably. The stylus pen was placed in almost the exact same location as the 3DS, but the Start and Select buttons have been moved towards the right-hand side of the bottom screen to accommodate players. The only thing that I was really disappointed with here was the noticeable lack of screen quality; comparative to about the DS Lite quality. Still, for the generous price point of the system ($130) and with full compatibility to all 3DS/most DS games, it will definitely sell with the young gamer audience it was intended for. Grab it this weekend on October 12th!
Legend of Zelda: A Link Between Worlds
My being a huge LoZ fan didn't change the fact that this game plays much smoother than any of the other modern, handheld Zelda titles out there. The frame rate was perfect and the attack/movement actions I made, such as swinging my sword and striking an enemy, were spot on. I also enjoyed the addition of the "magic meter" that sort of acted like a stamina bar; my bow and arrows never depleted, only my magic from my ever refilling magic meter. The game truly felt like an updated version of A Link to the Past from the SNES days. I'm very eager to explore the game more this coming November 22nd.
Wii Fit U
Finally, we got to try out the upcoming Wii Fit U many are waiting for. For those that haven't heard: don't worry about purchasing another Wii Fit balancing board. There is no new board being introduced to replace it, nor is it fully required, but there will be a fully packaged version available. A new device called the "Fit Meter" will be available to use in conjunction with your workout sessions and contributes to your Wii Fit U records. The device attaches to your belt will allow it to record many aspects of your daily routine and workouts, such as steps taken, distance traveled, burned calories, and my personal favorite, changes in altitude. This was implemented to better calculate when a person moves to a higher/lower elevation, such as running up a hill or walking down the stairs.
Furthermore, Wii Fit U will allow people to create their own custom communities via the Miiverse, to either workout with others over or keep members motivated. There are also a ton of new workout games and exercises to experience this time around, with players allowed to put them into customized workout routines. I had the chance to use both the Wii balancing board along with the GamePad to cater food to people; using the GamePad as the tray for balancing the food and the board to run the food over to the guests. It may have been silly to watch me play it, but I had a ton of fun doing it and got decent exercise as well. The free digital version of this releases on November 1st.
That's it for the general Nintendo overview. Stay tune for more on our impressions with Nintendo's upcoming, flagship co-op titles.
nintendo philly tour stop
Borderlands 3 Will Have Cross-Play "As Soon As Practicable," Not At Launch
SuperMassive's Man of Medan Will Feature Two Co-Op Modes
Borderlands 3 Will Have A Number of Co-Op QoL Improvements